wip
This commit is contained in:
parent
95310651d8
commit
1f9a9896e9
|
@ -36,7 +36,8 @@
|
|||
"got": "^11.8.6",
|
||||
"ioredis": "^5.3.1",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rxjs": "^7.2.0"
|
||||
"rxjs": "^7.2.0",
|
||||
"timezonecomplete": "^5.12.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "^9.0.0",
|
||||
|
@ -8576,6 +8577,14 @@
|
|||
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/timezonecomplete": {
|
||||
"version": "5.12.4",
|
||||
"resolved": "https://registry.npmjs.org/timezonecomplete/-/timezonecomplete-5.12.4.tgz",
|
||||
"integrity": "sha512-K+ocagBAl5wu9Ifh5oHKhRRLb0wP7j0VjAzjboZsT6bnVmtJNRe3Wnk2IPp0C4Uc8HpLly3gbfUrTlJ3M7vCPA==",
|
||||
"dependencies": {
|
||||
"tzdata": "^1.0.25"
|
||||
}
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||
|
@ -8867,6 +8876,11 @@
|
|||
"node": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tzdata": {
|
||||
"version": "1.0.38",
|
||||
"resolved": "https://registry.npmjs.org/tzdata/-/tzdata-1.0.38.tgz",
|
||||
"integrity": "sha512-KIgVvZTLt+DWzr3MOENNLCLdsNB+usedRYYHCVfVbA7TDewj8mfjlWmj3Mv6FfdrvfeE6Oprt+qE47YiL90duQ=="
|
||||
},
|
||||
"node_modules/uid": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz",
|
||||
|
|
|
@ -59,7 +59,8 @@
|
|||
"got": "^11.8.6",
|
||||
"ioredis": "^5.3.1",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rxjs": "^7.2.0"
|
||||
"rxjs": "^7.2.0",
|
||||
"timezonecomplete": "^5.12.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "^9.0.0",
|
||||
|
|
|
@ -7,6 +7,9 @@ import { CreateAdUseCase } from './domain/usecases/create-ad.usecase';
|
|||
import { AdRepository } from './adapters/secondaries/ad.repository';
|
||||
import { DatabaseModule } from '../database/database.module';
|
||||
import { CqrsModule } from '@nestjs/cqrs';
|
||||
import { Messager } from './adapters/secondaries/messager';
|
||||
import { TimezoneFinder } from './adapters/secondaries/timezone-finder';
|
||||
import { GeoTimezoneFinder } from '../geography/adapters/secondaries/geo-timezone-finder';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
@ -36,7 +39,14 @@ import { CqrsModule } from '@nestjs/cqrs';
|
|||
}),
|
||||
],
|
||||
controllers: [AdMessagerController],
|
||||
providers: [AdProfile, AdRepository, CreateAdUseCase],
|
||||
providers: [
|
||||
AdProfile,
|
||||
Messager,
|
||||
AdRepository,
|
||||
TimezoneFinder,
|
||||
GeoTimezoneFinder,
|
||||
CreateAdUseCase,
|
||||
],
|
||||
exports: [],
|
||||
})
|
||||
export class AdModule {}
|
||||
|
|
|
@ -6,51 +6,59 @@ import { Mapper } from '@automapper/core';
|
|||
import { CommandBus } from '@nestjs/cqrs';
|
||||
import { CreateAdCommand } from '../../commands/create-ad.command';
|
||||
import { CreateAdRequest } from '../../domain/dtos/create-ad.request';
|
||||
import { ValidationError, validateOrReject } from 'class-validator';
|
||||
import { validateOrReject } from 'class-validator';
|
||||
import { Messager } from '../secondaries/messager';
|
||||
import { GeoTimezoneFinder } from 'src/modules/geography/adapters/secondaries/geo-timezone-finder';
|
||||
|
||||
@Controller()
|
||||
export class AdMessagerController {
|
||||
constructor(
|
||||
private readonly messager: Messager,
|
||||
private readonly commandBus: CommandBus,
|
||||
@InjectMapper() private readonly mapper: Mapper,
|
||||
private readonly timezoneFinder: GeoTimezoneFinder,
|
||||
) {}
|
||||
|
||||
@RabbitSubscribe({
|
||||
name: 'adCreated',
|
||||
})
|
||||
async adCreatedHandler(message: string): Promise<void> {
|
||||
let createAdRequest: CreateAdRequest;
|
||||
try {
|
||||
// parse message to conform to CreateAdRequest (not a real instance yet)
|
||||
const parsedMessage: CreateAdRequest = JSON.parse(message);
|
||||
console.log(parsedMessage);
|
||||
// create a real instance of CreateAdRequest from parsed message
|
||||
// const createAdRequest: CreateAdRequest = this.mapper.map(
|
||||
// parsedMessage,
|
||||
// CreateAdRequest,
|
||||
// CreateAdRequest,
|
||||
// );
|
||||
const createAdRequest = new CreateAdRequest();
|
||||
createAdRequest.originType = parsedMessage.originType;
|
||||
createAdRequest.destinationType = parsedMessage.destinationType;
|
||||
createAdRequest.waypoints = parsedMessage.waypoints.map((waypoint) => ({
|
||||
lon: waypoint.lon,
|
||||
lat: waypoint.lat,
|
||||
}));
|
||||
console.log(createAdRequest);
|
||||
createAdRequest = this.mapper.map(
|
||||
parsedMessage,
|
||||
CreateAdRequest,
|
||||
CreateAdRequest,
|
||||
);
|
||||
// validate instance
|
||||
await validateOrReject(createAdRequest.waypoints[0]);
|
||||
await validateOrReject(createAdRequest);
|
||||
// validate nested objects (fixes direct nested validation bug)
|
||||
for (const waypoint of createAdRequest.waypoints) {
|
||||
try {
|
||||
await validateOrReject(waypoint);
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
createAdRequest.timezone = this.timezoneFinder.timezones(
|
||||
createAdRequest.waypoints[0].lon,
|
||||
createAdRequest.waypoints[0].lat,
|
||||
)[0];
|
||||
const ad: Ad = await this.commandBus.execute(
|
||||
new CreateAdCommand(createAdRequest),
|
||||
);
|
||||
console.log(ad);
|
||||
} catch (e) {
|
||||
if (Array.isArray(e)) {
|
||||
e.forEach((error) =>
|
||||
error instanceof ValidationError
|
||||
? console.log(error.constraints)
|
||||
: console.log(error),
|
||||
);
|
||||
}
|
||||
this.messager.publish(
|
||||
'logging.matcher.ad.crit',
|
||||
JSON.stringify({
|
||||
createAdRequest,
|
||||
error: e,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export abstract class MessageBroker {
|
||||
exchange: string;
|
||||
|
||||
constructor(exchange: string) {
|
||||
this.exchange = exchange;
|
||||
}
|
||||
|
||||
abstract publish(routingKey: string, message: string): void;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { MessageBroker } from './message-broker';
|
||||
|
||||
@Injectable()
|
||||
export class Messager extends MessageBroker {
|
||||
constructor(
|
||||
private readonly _amqpConnection: AmqpConnection,
|
||||
configService: ConfigService,
|
||||
) {
|
||||
super(configService.get<string>('RMQ_EXCHANGE'));
|
||||
}
|
||||
|
||||
publish = (routingKey: string, message: string): void => {
|
||||
this._amqpConnection.publish(this.exchange, routingKey, message);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { GeoTimezoneFinder } from '../../../geography/adapters/secondaries/geo-timezone-finder';
|
||||
import { IFindTimezone } from '../../../geography/domain/interfaces/timezone-finder.interface';
|
||||
|
||||
@Injectable()
|
||||
export class TimezoneFinder implements IFindTimezone {
|
||||
constructor(private readonly geoTimezoneFinder: GeoTimezoneFinder) {}
|
||||
|
||||
timezones = (lon: number, lat: number): string[] =>
|
||||
this.geoTimezoneFinder.timezones(lon, lat);
|
||||
}
|
|
@ -8,12 +8,10 @@ import {
|
|||
IsNumber,
|
||||
IsOptional,
|
||||
IsString,
|
||||
ValidateNested,
|
||||
} from 'class-validator';
|
||||
import { PointType } from '../../../geography/domain/types/point-type.enum';
|
||||
import { Frequency } from '../types/frequency.enum';
|
||||
import { Coordinates } from '../../../geography/domain/types/coordinates.type';
|
||||
import { Type } from 'class-transformer';
|
||||
import { Coordinates } from '../../../geography/domain/entities/coordinates';
|
||||
|
||||
export class CreateAdRequest {
|
||||
@IsString()
|
||||
|
@ -114,9 +112,7 @@ export class CreateAdRequest {
|
|||
destinationType: PointType;
|
||||
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
@ArrayMinSize(2)
|
||||
@Type(() => Coordinates)
|
||||
@AutoMap(() => [Coordinates])
|
||||
waypoints: Coordinates[];
|
||||
|
||||
|
@ -140,4 +136,6 @@ export class CreateAdRequest {
|
|||
@IsString()
|
||||
@AutoMap()
|
||||
updatedAt: string;
|
||||
|
||||
timezone: string;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { AutoMap } from '@automapper/classes';
|
||||
import { PointType } from '../../../geography/domain/types/point-type.enum';
|
||||
import { Coordinates } from '../../../geography/domain/types/coordinates.type';
|
||||
import { Coordinates } from '../../../geography/domain/entities/coordinates';
|
||||
|
||||
export class Ad {
|
||||
@AutoMap()
|
||||
|
@ -22,7 +22,7 @@ export class Ad {
|
|||
toDate: Date;
|
||||
|
||||
@AutoMap()
|
||||
monTime: string;
|
||||
monTime: Date;
|
||||
|
||||
@AutoMap()
|
||||
tueTime: string;
|
||||
|
|
|
@ -4,7 +4,8 @@ import { Injectable } from '@nestjs/common';
|
|||
import { Ad } from '../domain/entities/ad';
|
||||
import { AdPresenter } from '../adapters/primaries/ad.presenter';
|
||||
import { CreateAdRequest } from '../domain/dtos/create-ad.request';
|
||||
import { Coordinates } from 'src/modules/geography/domain/types/coordinates.type';
|
||||
import { Coordinates } from '../../geography/domain/entities/coordinates';
|
||||
import moment from 'moment-timezone';
|
||||
|
||||
@Injectable()
|
||||
export class AdProfile extends AutomapperProfile {
|
||||
|
@ -21,16 +22,14 @@ export class AdProfile extends AutomapperProfile {
|
|||
CreateAdRequest,
|
||||
forMember(
|
||||
(dest) => dest.waypoints,
|
||||
mapFrom(
|
||||
(source) =>
|
||||
source.waypoints.map(
|
||||
(waypoint) =>
|
||||
new Coordinates(
|
||||
waypoint.lon ?? undefined,
|
||||
waypoint.lat ?? undefined,
|
||||
),
|
||||
),
|
||||
// .filter((waypoint) => waypoint),
|
||||
mapFrom((source) =>
|
||||
source.waypoints.map(
|
||||
(waypoint) =>
|
||||
new Coordinates(
|
||||
waypoint.lon ?? undefined,
|
||||
waypoint.lat ?? undefined,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -54,6 +53,18 @@ export class AdProfile extends AutomapperProfile {
|
|||
(dest) => dest.updatedAt,
|
||||
mapFrom((source) => new Date(source.updatedAt)),
|
||||
),
|
||||
// forMember(
|
||||
// (dest) => dest.monTime,
|
||||
// mapFrom((source) =>
|
||||
// source.monTime
|
||||
// ? new Date(
|
||||
// moment
|
||||
// .tz(`${source.fromDate} ${source.monTime}`, source.timezone)
|
||||
// .format(),
|
||||
// )
|
||||
// : undefined,
|
||||
// ),
|
||||
// ),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
import { createMap, Mapper } from '@automapper/core';
|
||||
import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Coordinates } from '../../geography/domain/types/coordinates.type';
|
||||
|
||||
@Injectable()
|
||||
export class CoordinatesProfile extends AutomapperProfile {
|
||||
constructor(@InjectMapper() mapper: Mapper) {
|
||||
super(mapper);
|
||||
}
|
||||
|
||||
override get profile() {
|
||||
return (mapper: any) => {
|
||||
createMap(mapper, Coordinates, Coordinates);
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import { PointType } from './point-type.enum';
|
||||
import { Coordinates } from './coordinates.type';
|
||||
import { Coordinates } from '../entities/coordinates';
|
||||
|
||||
export type Point = Coordinates & {
|
||||
type?: PointType;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Coordinates } from 'src/modules/geography/domain/types/coordinates.type';
|
||||
import { Coordinates } from '../../../../geography/domain/entities/coordinates';
|
||||
|
||||
export class SpacetimePoint {
|
||||
coordinates: Coordinates;
|
||||
|
|
|
@ -11,7 +11,6 @@ import { Day } from '../../types/day.type';
|
|||
|
||||
export class Time {
|
||||
private timeRequest: IRequestTime;
|
||||
private defaultMarginDuration: number;
|
||||
private defaultValidityDuration: number;
|
||||
frequency: Frequency;
|
||||
fromDate: Date;
|
||||
|
@ -25,7 +24,6 @@ export class Time {
|
|||
defaultValidityDuration: number,
|
||||
) {
|
||||
this.timeRequest = timeRequest;
|
||||
this.defaultMarginDuration = defaultMarginDuration;
|
||||
this.defaultValidityDuration = defaultValidityDuration;
|
||||
this.schedule = {};
|
||||
this.marginDurations = {
|
||||
|
|
Loading…
Reference in New Issue