basic ad entity without direction

This commit is contained in:
sbriat 2023-08-18 16:50:55 +02:00
parent db13f4d87e
commit 88326dcf6f
10 changed files with 74 additions and 10 deletions

7
package-lock.json generated
View File

@ -49,6 +49,7 @@
"@types/jest": "29.5.0", "@types/jest": "29.5.0",
"@types/node": "18.15.11", "@types/node": "18.15.11",
"@types/supertest": "^2.0.11", "@types/supertest": "^2.0.11",
"@types/uuid": "^9.0.2",
"@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0", "@typescript-eslint/parser": "^5.0.0",
"dotenv-cli": "^7.2.1", "dotenv-cli": "^7.2.1",
@ -2655,6 +2656,12 @@
"@types/superagent": "*" "@types/superagent": "*"
} }
}, },
"node_modules/@types/uuid": {
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz",
"integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==",
"dev": true
},
"node_modules/@types/validator": { "node_modules/@types/validator": {
"version": "13.11.1", "version": "13.11.1",
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.1.tgz", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.1.tgz",

View File

@ -70,6 +70,7 @@
"@types/jest": "29.5.0", "@types/jest": "29.5.0",
"@types/node": "18.15.11", "@types/node": "18.15.11",
"@types/supertest": "^2.0.11", "@types/supertest": "^2.0.11",
"@types/uuid": "^9.0.2",
"@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0", "@typescript-eslint/parser": "^5.0.0",
"dotenv-cli": "^7.2.1", "dotenv-cli": "^7.2.1",

View File

@ -63,6 +63,6 @@ import { GeographyModule } from '@modules/geography/geography.module';
GeographyModule, GeographyModule,
MessagerModule, MessagerModule,
], ],
exports: [AdModule, MessagerModule], exports: [AdModule, GeographyModule, MessagerModule],
}) })
export class AppModule {} export class AppModule {}

View File

@ -1,3 +1,4 @@
export const AD_REPOSITORY = Symbol('AD_REPOSITORY'); export const AD_REPOSITORY = Symbol('AD_REPOSITORY');
export const GEOROUTER = Symbol('GEOROUTER'); export const GEOROUTER = Symbol('GEOROUTER');
export const AD_DIRECTION_ENCODER = Symbol('AD_DIRECTION_ENCODER');
export const AD_MESSAGE_PUBLISHER = Symbol('AD_MESSAGE_PUBLISHER'); export const AD_MESSAGE_PUBLISHER = Symbol('AD_MESSAGE_PUBLISHER');

View File

@ -1,5 +1,5 @@
import { Mapper } from '@mobicoop/ddd-library'; import { Mapper } from '@mobicoop/ddd-library';
import { Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { AdEntity } from './core/domain/ad.entity'; import { AdEntity } from './core/domain/ad.entity';
import { import {
AdWriteModel, AdWriteModel,
@ -9,6 +9,8 @@ import {
import { Frequency } from './core/domain/ad.types'; import { Frequency } from './core/domain/ad.types';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
import { ScheduleItemProps } from './core/domain/value-objects/schedule-item.value-object'; import { ScheduleItemProps } from './core/domain/value-objects/schedule-item.value-object';
import { DirectionEncoderPort } from '@modules/geography/core/application/ports/direction-encoder.port';
import { AD_DIRECTION_ENCODER } from './ad.di-tokens';
/** /**
* Mapper constructs objects that are used in different layers: * Mapper constructs objects that are used in different layers:
@ -21,6 +23,11 @@ import { ScheduleItemProps } from './core/domain/value-objects/schedule-item.val
export class AdMapper export class AdMapper
implements Mapper<AdEntity, AdReadModel, AdWriteModel, undefined> implements Mapper<AdEntity, AdReadModel, AdWriteModel, undefined>
{ {
constructor(
@Inject(AD_DIRECTION_ENCODER)
private readonly directionEncoder: DirectionEncoderPort,
) {}
toPersistence = (entity: AdEntity): AdWriteModel => { toPersistence = (entity: AdEntity): AdWriteModel => {
const copy = entity.getProps(); const copy = entity.getProps();
const now = new Date(); const now = new Date();
@ -54,7 +61,7 @@ export class AdMapper
driverDistance: copy.driverDistance, driverDistance: copy.driverDistance,
passengerDuration: copy.passengerDuration, passengerDuration: copy.passengerDuration,
passengerDistance: copy.passengerDistance, passengerDistance: copy.passengerDistance,
waypoints: '', waypoints: this.directionEncoder.encode(copy.waypoints),
direction: '', direction: '',
fwdAzimuth: copy.fwdAzimuth, fwdAzimuth: copy.fwdAzimuth,
backAzimuth: copy.backAzimuth, backAzimuth: copy.backAzimuth,

View File

@ -1,11 +1,16 @@
import { Module, Provider } from '@nestjs/common'; import { Module, Provider } from '@nestjs/common';
import { CqrsModule } from '@nestjs/cqrs'; import { CqrsModule } from '@nestjs/cqrs';
import { AD_MESSAGE_PUBLISHER, AD_REPOSITORY } from './ad.di-tokens'; import {
AD_MESSAGE_PUBLISHER,
AD_REPOSITORY,
AD_DIRECTION_ENCODER,
} from './ad.di-tokens';
import { MessageBrokerPublisher } from '@mobicoop/message-broker-module'; import { MessageBrokerPublisher } from '@mobicoop/message-broker-module';
import { AdRepository } from './infrastructure/ad.repository'; import { AdRepository } from './infrastructure/ad.repository';
import { PrismaService } from './infrastructure/prisma.service'; import { PrismaService } from './infrastructure/prisma.service';
import { AdMapper } from './ad.mapper'; import { AdMapper } from './ad.mapper';
import { AdCreatedMessageHandler } from './interface/message-handlers/ad-created.message-handler'; import { AdCreatedMessageHandler } from './interface/message-handlers/ad-created.message-handler';
import { PostgresDirectionEncoder } from '@modules/geography/infrastructure/postgres-direction-encoder';
const messageHandlers = [AdCreatedMessageHandler]; const messageHandlers = [AdCreatedMessageHandler];
@ -24,8 +29,16 @@ const messagePublishers: Provider[] = [
useExisting: MessageBrokerPublisher, useExisting: MessageBrokerPublisher,
}, },
]; ];
const orms: Provider[] = [PrismaService]; const orms: Provider[] = [PrismaService];
const adapters: Provider[] = [
{
provide: AD_DIRECTION_ENCODER,
useClass: PostgresDirectionEncoder,
},
];
@Module({ @Module({
imports: [CqrsModule], imports: [CqrsModule],
providers: [ providers: [
@ -34,7 +47,8 @@ const orms: Provider[] = [PrismaService];
...repositories, ...repositories,
...messagePublishers, ...messagePublishers,
...orms, ...orms,
...adapters,
], ],
exports: [PrismaService, AdMapper, AD_REPOSITORY], exports: [PrismaService, AdMapper, AD_REPOSITORY, AD_DIRECTION_ENCODER],
}) })
export class AdModule {} export class AdModule {}

View File

@ -1,3 +1,4 @@
import { AD_DIRECTION_ENCODER } from '@modules/ad/ad.di-tokens';
import { AdMapper } from '@modules/ad/ad.mapper'; import { AdMapper } from '@modules/ad/ad.mapper';
import { AdEntity } from '@modules/ad/core/domain/ad.entity'; import { AdEntity } from '@modules/ad/core/domain/ad.entity';
import { Frequency } from '@modules/ad/core/domain/ad.types'; import { Frequency } from '@modules/ad/core/domain/ad.types';
@ -5,6 +6,7 @@ import {
AdReadModel, AdReadModel,
AdWriteModel, AdWriteModel,
} from '@modules/ad/infrastructure/ad.repository'; } from '@modules/ad/infrastructure/ad.repository';
import { DirectionEncoderPort } from '@modules/geography/core/application/ports/direction-encoder.port';
import { Test } from '@nestjs/testing'; import { Test } from '@nestjs/testing';
const now = new Date('2023-06-21 06:00:00'); const now = new Date('2023-06-21 06:00:00');
@ -76,12 +78,26 @@ const adReadModel: AdReadModel = {
updatedAt: now, updatedAt: now,
}; };
const mockDirectionEncoder: DirectionEncoderPort = {
encode: jest
.fn()
.mockImplementation(
() => "'LINESTRING(6.1765102 48.689445,2.3522 48.8566)'",
),
};
describe('Ad Mapper', () => { describe('Ad Mapper', () => {
let adMapper: AdMapper; let adMapper: AdMapper;
beforeAll(async () => { beforeAll(async () => {
const module = await Test.createTestingModule({ const module = await Test.createTestingModule({
providers: [AdMapper], providers: [
AdMapper,
{
provide: AD_DIRECTION_ENCODER,
useValue: mockDirectionEncoder,
},
],
}).compile(); }).compile();
adMapper = module.get<AdMapper>(AdMapper); adMapper = module.get<AdMapper>(AdMapper);
}); });
@ -93,6 +109,9 @@ describe('Ad Mapper', () => {
it('should map domain entity to persistence data', async () => { it('should map domain entity to persistence data', async () => {
const mapped: AdWriteModel = adMapper.toPersistence(adEntity); const mapped: AdWriteModel = adMapper.toPersistence(adEntity);
expect(mapped.schedule.create.length).toBe(1); expect(mapped.schedule.create.length).toBe(1);
expect(mapped.waypoints).toBe(
"'LINESTRING(6.1765102 48.689445,2.3522 48.8566)'",
);
}); });
it('should map persisted data to domain entity', async () => { it('should map persisted data to domain entity', async () => {

View File

@ -1,6 +1,8 @@
import { AD_DIRECTION_ENCODER } from '@modules/ad/ad.di-tokens';
import { AdMapper } from '@modules/ad/ad.mapper'; import { AdMapper } from '@modules/ad/ad.mapper';
import { AdRepository } from '@modules/ad/infrastructure/ad.repository'; import { AdRepository } from '@modules/ad/infrastructure/ad.repository';
import { PrismaService } from '@modules/ad/infrastructure/prisma.service'; import { PrismaService } from '@modules/ad/infrastructure/prisma.service';
import { DirectionEncoderPort } from '@modules/geography/core/application/ports/direction-encoder.port';
import { EventEmitter2, EventEmitterModule } from '@nestjs/event-emitter'; import { EventEmitter2, EventEmitterModule } from '@nestjs/event-emitter';
import { Test, TestingModule } from '@nestjs/testing'; import { Test, TestingModule } from '@nestjs/testing';
@ -8,6 +10,10 @@ const mockMessagePublisher = {
publish: jest.fn().mockImplementation(), publish: jest.fn().mockImplementation(),
}; };
const mockDirectionEncoder: DirectionEncoderPort = {
encode: jest.fn(),
};
describe('Ad repository', () => { describe('Ad repository', () => {
let prismaService: PrismaService; let prismaService: PrismaService;
let adMapper: AdMapper; let adMapper: AdMapper;
@ -16,7 +22,14 @@ describe('Ad repository', () => {
beforeAll(async () => { beforeAll(async () => {
const module: TestingModule = await Test.createTestingModule({ const module: TestingModule = await Test.createTestingModule({
imports: [EventEmitterModule.forRoot()], imports: [EventEmitterModule.forRoot()],
providers: [PrismaService, AdMapper], providers: [
PrismaService,
AdMapper,
{
provide: AD_DIRECTION_ENCODER,
useValue: mockDirectionEncoder,
},
],
}).compile(); }).compile();
prismaService = module.get<PrismaService>(PrismaService); prismaService = module.get<PrismaService>(PrismaService);

View File

@ -5,9 +5,9 @@ import { DefaultParams } from '../core/application/types/default-params.type';
@Injectable() @Injectable()
export class DefaultParamsProvider implements DefaultParamsProviderPort { export class DefaultParamsProvider implements DefaultParamsProviderPort {
constructor(private readonly _configService: ConfigService) {} constructor(private readonly configService: ConfigService) {}
getParams = (): DefaultParams => ({ getParams = (): DefaultParams => ({
GEOROUTER_TYPE: this._configService.get('GEOROUTER_TYPE'), GEOROUTER_TYPE: this.configService.get('GEOROUTER_TYPE'),
GEOROUTER_URL: this._configService.get('GEOROUTER_URL'), GEOROUTER_URL: this.configService.get('GEOROUTER_URL'),
}); });
} }

View File

@ -1,6 +1,8 @@
import { Coordinates } from '../core/application/types/coordinates.type'; import { Coordinates } from '../core/application/types/coordinates.type';
import { DirectionEncoderPort } from '../core/application/ports/direction-encoder.port'; import { DirectionEncoderPort } from '../core/application/ports/direction-encoder.port';
import { Injectable } from '@nestjs/common';
@Injectable()
export class PostgresDirectionEncoder implements DirectionEncoderPort { export class PostgresDirectionEncoder implements DirectionEncoderPort {
encode = (coordinates: Coordinates[]): string => encode = (coordinates: Coordinates[]): string =>
[ [