use strict null checks
This commit is contained in:
parent
effe51b9a2
commit
f15e7d11b1
|
@ -13,7 +13,7 @@
|
|||
"@grpc/proto-loader": "^0.7.6",
|
||||
"@liaoliaots/nestjs-redis": "^9.0.5",
|
||||
"@mobicoop/configuration-module": "^1.2.0",
|
||||
"@mobicoop/ddd-library": "^1.1.0",
|
||||
"@mobicoop/ddd-library": "file:../../packages/dddlibrary",
|
||||
"@mobicoop/health-module": "^2.0.0",
|
||||
"@mobicoop/message-broker-module": "^1.2.0",
|
||||
"@nestjs/axios": "^2.0.0",
|
||||
|
@ -1505,9 +1505,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@mobicoop/ddd-library": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@mobicoop/ddd-library/-/ddd-library-1.1.0.tgz",
|
||||
"integrity": "sha512-x4X7j2CJYZQPDZgLuZP5TFk59fle1wTPdX++Z2YyD7VwwV+yOmVvMIRfTyLRFUTzLObrd6FKs8mh+g59n9jUlA==",
|
||||
"version": "1.1.1",
|
||||
"resolved": "file:../../packages/dddlibrary",
|
||||
"license": "AGPL",
|
||||
"dependencies": {
|
||||
"@nestjs/event-emitter": "^1.4.2",
|
||||
"@nestjs/microservices": "^9.4.0",
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
"@grpc/proto-loader": "^0.7.6",
|
||||
"@liaoliaots/nestjs-redis": "^9.0.5",
|
||||
"@mobicoop/configuration-module": "^1.2.0",
|
||||
"@mobicoop/ddd-library": "^1.1.0",
|
||||
"@mobicoop/ddd-library": "file:../../packages/dddlibrary",
|
||||
"@mobicoop/health-module": "^2.0.0",
|
||||
"@mobicoop/message-broker-module": "^1.2.0",
|
||||
"@nestjs/axios": "^2.0.0",
|
||||
|
|
|
@ -18,7 +18,7 @@ export class CreateAdCommand extends Command {
|
|||
|
||||
constructor(props: CommandProps<CreateAdCommand>) {
|
||||
super(props);
|
||||
this.id = props.id;
|
||||
this.id = props.id as string;
|
||||
this.driver = props.driver;
|
||||
this.passenger = props.passenger;
|
||||
this.frequency = props.frequency;
|
||||
|
|
|
@ -18,10 +18,10 @@ export type AdBaseModel = {
|
|||
seatsProposed: number;
|
||||
seatsRequested: number;
|
||||
strict: boolean;
|
||||
driverDuration: number;
|
||||
driverDistance: number;
|
||||
passengerDuration: number;
|
||||
passengerDistance: number;
|
||||
driverDuration?: number;
|
||||
driverDistance?: number;
|
||||
passengerDuration?: number;
|
||||
passengerDistance?: number;
|
||||
fwdAzimuth: number;
|
||||
backAzimuth: number;
|
||||
createdAt: Date;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export type DefaultParams = {
|
||||
GEOROUTER_TYPE: string;
|
||||
GEOROUTER_URL: string;
|
||||
GEOROUTER_TYPE?: string;
|
||||
GEOROUTER_URL?: string;
|
||||
};
|
||||
|
|
|
@ -25,8 +25,9 @@ export class RouteEntity extends AggregateRoot<RouteProps> {
|
|||
} catch (e: any) {
|
||||
throw e;
|
||||
}
|
||||
let driverRoute: Route;
|
||||
let passengerRoute: Route;
|
||||
let baseRoute: Route;
|
||||
let driverRoute: Route | undefined;
|
||||
let passengerRoute: Route | undefined;
|
||||
if (routes.some((route: Route) => route.type == PathType.GENERIC)) {
|
||||
driverRoute = passengerRoute = routes.find(
|
||||
(route: Route) => route.type == PathType.GENERIC,
|
||||
|
@ -41,22 +42,21 @@ export class RouteEntity extends AggregateRoot<RouteProps> {
|
|||
? routes.find((route: Route) => route.type == PathType.PASSENGER)
|
||||
: undefined;
|
||||
}
|
||||
if (driverRoute) {
|
||||
baseRoute = driverRoute;
|
||||
} else {
|
||||
baseRoute = passengerRoute as Route;
|
||||
}
|
||||
const routeProps: RouteProps = {
|
||||
driverDistance: driverRoute?.distance,
|
||||
driverDuration: driverRoute?.duration,
|
||||
passengerDistance: passengerRoute?.distance,
|
||||
passengerDuration: passengerRoute?.duration,
|
||||
fwdAzimuth: driverRoute
|
||||
? driverRoute.fwdAzimuth
|
||||
: passengerRoute.fwdAzimuth,
|
||||
backAzimuth: driverRoute
|
||||
? driverRoute.backAzimuth
|
||||
: passengerRoute.backAzimuth,
|
||||
distanceAzimuth: driverRoute
|
||||
? driverRoute.distanceAzimuth
|
||||
: passengerRoute.distanceAzimuth,
|
||||
fwdAzimuth: baseRoute.fwdAzimuth,
|
||||
backAzimuth: baseRoute.backAzimuth,
|
||||
distanceAzimuth: baseRoute.distanceAzimuth,
|
||||
waypoints: create.waypoints,
|
||||
points: driverRoute ? driverRoute.points : passengerRoute.points,
|
||||
points: baseRoute.points,
|
||||
};
|
||||
return new RouteEntity({
|
||||
id: v4(),
|
||||
|
@ -111,52 +111,3 @@ export class RouteEntity extends AggregateRoot<RouteProps> {
|
|||
points,
|
||||
});
|
||||
}
|
||||
|
||||
// import { IGeodesic } from '../interfaces/geodesic.interface';
|
||||
// import { Point } from '../types/point.type';
|
||||
// import { SpacetimePoint } from './spacetime-point';
|
||||
|
||||
// export class Route {
|
||||
// distance: number;
|
||||
// duration: number;
|
||||
// fwdAzimuth: number;
|
||||
// backAzimuth: number;
|
||||
// distanceAzimuth: number;
|
||||
// points: Point[];
|
||||
// spacetimePoints: SpacetimePoint[];
|
||||
// private geodesic: IGeodesic;
|
||||
|
||||
// constructor(geodesic: IGeodesic) {
|
||||
// this.distance = undefined;
|
||||
// this.duration = undefined;
|
||||
// this.fwdAzimuth = undefined;
|
||||
// this.backAzimuth = undefined;
|
||||
// this.distanceAzimuth = undefined;
|
||||
// this.points = [];
|
||||
// this.spacetimePoints = [];
|
||||
// this.geodesic = geodesic;
|
||||
// }
|
||||
|
||||
// setPoints = (points: Point[]): void => {
|
||||
// this.points = points;
|
||||
// this.setAzimuth(points);
|
||||
// };
|
||||
|
||||
// setSpacetimePoints = (spacetimePoints: SpacetimePoint[]): void => {
|
||||
// this.spacetimePoints = spacetimePoints;
|
||||
// };
|
||||
|
||||
// protected setAzimuth = (points: Point[]): void => {
|
||||
// const inverse = this.geodesic.inverse(
|
||||
// points[0].lon,
|
||||
// points[0].lat,
|
||||
// points[points.length - 1].lon,
|
||||
// points[points.length - 1].lat,
|
||||
// );
|
||||
// this.fwdAzimuth =
|
||||
// inverse.azimuth >= 0 ? inverse.azimuth : 360 - Math.abs(inverse.azimuth);
|
||||
// this.backAzimuth =
|
||||
// this.fwdAzimuth > 180 ? this.fwdAzimuth - 180 : this.fwdAzimuth + 180;
|
||||
// this.distanceAzimuth = inverse.distance;
|
||||
// };
|
||||
// }
|
||||
|
|
|
@ -52,7 +52,7 @@ export type Waypoint = Coordinates & {
|
|||
|
||||
export type SpacetimePoint = Coordinates & {
|
||||
duration: number;
|
||||
distance: number;
|
||||
distance?: number;
|
||||
};
|
||||
|
||||
export enum Role {
|
||||
|
|
|
@ -22,6 +22,7 @@ export class Geodesic implements GeodesicPort {
|
|||
lat2,
|
||||
lon2,
|
||||
);
|
||||
if (!azimuth || !distance) throw new Error('Azimuth not found');
|
||||
return { azimuth, distance };
|
||||
};
|
||||
}
|
||||
|
|
|
@ -72,11 +72,12 @@ export class GraphhopperGeorouter implements GeorouterPort {
|
|||
.map((point) => [point.lat, point.lon].join('%2C'))
|
||||
.join('&point='),
|
||||
].join('');
|
||||
const route = await lastValueFrom(
|
||||
return await lastValueFrom(
|
||||
this.httpService.get(url).pipe(
|
||||
map((res) =>
|
||||
res.data ? this.createRoute(res, path.type) : undefined,
|
||||
),
|
||||
map((response) => {
|
||||
if (response.data) return this.createRoute(response, path.type);
|
||||
throw new Error();
|
||||
}),
|
||||
catchError((error: AxiosError) => {
|
||||
if (error.code == AxiosError.ERR_BAD_REQUEST) {
|
||||
throw new RouteNotFoundException(
|
||||
|
@ -88,7 +89,6 @@ export class GraphhopperGeorouter implements GeorouterPort {
|
|||
}),
|
||||
),
|
||||
);
|
||||
return route;
|
||||
}),
|
||||
);
|
||||
return routes;
|
||||
|
@ -156,12 +156,20 @@ export class GraphhopperGeorouter implements GeorouterPort {
|
|||
const indices = this.getIndices(points, snappedWaypoints);
|
||||
const times = this.getTimes(durations, indices);
|
||||
const distances = this.getDistances(instructions, indices);
|
||||
return indices.map((index) => ({
|
||||
lon: points[index][1],
|
||||
lat: points[index][0],
|
||||
distance: distances.find((distance) => distance.index == index)?.distance,
|
||||
duration: times.find((time) => time.index == index)?.duration,
|
||||
}));
|
||||
return indices.map((index) => {
|
||||
const duration = times.find((time) => time.index == index);
|
||||
if (!duration)
|
||||
throw new Error(`Duration not found for waypoint #${index}`);
|
||||
const distance = distances.find((distance) => distance.index == index);
|
||||
if (!distance && instructions.length > 0)
|
||||
throw new Error(`Distance not found for waypoint #${index}`);
|
||||
return {
|
||||
lon: points[index][1],
|
||||
lat: points[index][0],
|
||||
distance: distance?.distance,
|
||||
duration: duration.duration,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
private getIndices = (
|
||||
|
@ -182,7 +190,7 @@ export class GraphhopperGeorouter implements GeorouterPort {
|
|||
index: number;
|
||||
originIndex: number;
|
||||
waypoint: number[];
|
||||
nearest: number;
|
||||
nearest?: number;
|
||||
distance: number;
|
||||
}
|
||||
>{
|
||||
|
@ -209,7 +217,7 @@ export class GraphhopperGeorouter implements GeorouterPort {
|
|||
}
|
||||
}
|
||||
for (const missedWaypoint of missedWaypoints) {
|
||||
indices[missedWaypoint.originIndex] = missedWaypoint.nearest;
|
||||
indices[missedWaypoint.originIndex] = missedWaypoint.nearest as number;
|
||||
}
|
||||
return indices;
|
||||
};
|
||||
|
|
|
@ -14,26 +14,20 @@ import { RouteResponseDto } from './interface/dtos/route.response.dto';
|
|||
export class RouteMapper
|
||||
implements Mapper<RouteEntity, undefined, undefined, RouteResponseDto>
|
||||
{
|
||||
toPersistence = (): undefined => {
|
||||
return undefined;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
toDomain = (): undefined => {
|
||||
return undefined;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
toResponse = (entity: RouteEntity): RouteResponseDto => {
|
||||
const response = new RouteResponseDto();
|
||||
response.driverDistance = Math.round(entity.getProps().driverDistance);
|
||||
response.driverDuration = Math.round(entity.getProps().driverDuration);
|
||||
response.passengerDistance = Math.round(
|
||||
entity.getProps().passengerDistance,
|
||||
);
|
||||
response.passengerDuration = Math.round(
|
||||
entity.getProps().passengerDuration,
|
||||
);
|
||||
response.driverDistance = entity.getProps().driverDistance
|
||||
? Math.round(entity.getProps().driverDistance as number)
|
||||
: undefined;
|
||||
response.driverDuration = entity.getProps().driverDuration
|
||||
? Math.round(entity.getProps().driverDuration as number)
|
||||
: undefined;
|
||||
response.passengerDistance = entity.getProps().passengerDistance
|
||||
? Math.round(entity.getProps().passengerDistance as number)
|
||||
: undefined;
|
||||
response.passengerDuration = entity.getProps().passengerDuration
|
||||
? Math.round(entity.getProps().passengerDuration as number)
|
||||
: undefined;
|
||||
response.fwdAzimuth = Math.round(entity.getProps().fwdAzimuth);
|
||||
response.backAzimuth = Math.round(entity.getProps().backAzimuth);
|
||||
response.distanceAzimuth = Math.round(entity.getProps().distanceAzimuth);
|
||||
|
|
|
@ -8,7 +8,7 @@ describe('Matcher geodesic', () => {
|
|||
it('should get inverse values', () => {
|
||||
const geodesic: Geodesic = new Geodesic();
|
||||
const inv = geodesic.inverse(0, 0, 1, 1);
|
||||
expect(Math.round(inv.azimuth)).toBe(45);
|
||||
expect(Math.round(inv.distance)).toBe(156900);
|
||||
expect(Math.round(inv.azimuth as number)).toBe(45);
|
||||
expect(Math.round(inv.distance as number)).toBe(156900);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -16,14 +16,6 @@ describe('Route Mapper', () => {
|
|||
expect(routeMapper).toBeDefined();
|
||||
});
|
||||
|
||||
it('should map domain entity to persistence data', async () => {
|
||||
expect(routeMapper.toPersistence()).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should map persisted data to domain entity', async () => {
|
||||
expect(routeMapper.toDomain()).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should map domain entity to response', async () => {
|
||||
const now = new Date();
|
||||
const routeEntity: RouteEntity = new RouteEntity({
|
||||
|
|
|
@ -1,17 +1,11 @@
|
|||
import { WaypointDto } from '../waypoint.dto';
|
||||
|
||||
export const hasValidPositionIndexes = (waypoints: WaypointDto[]): boolean => {
|
||||
if (!waypoints) return false;
|
||||
if (waypoints.length == 0) return false;
|
||||
if (waypoints.every((waypoint) => waypoint.position === undefined))
|
||||
return false;
|
||||
if (waypoints.every((waypoint) => typeof waypoint.position === 'number')) {
|
||||
const positions = Array.from(waypoints, (waypoint) => waypoint.position);
|
||||
positions.sort();
|
||||
for (let i = 1; i < positions.length; i++)
|
||||
if (positions[i] != positions[i - 1] + 1) return false;
|
||||
const positions = Array.from(waypoints, (waypoint) => waypoint.position);
|
||||
positions.sort();
|
||||
for (let i = 1; i < positions.length; i++)
|
||||
if (positions[i] != positions[i - 1] + 1) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { IsInt, IsOptional } from 'class-validator';
|
||||
import { IsInt } from 'class-validator';
|
||||
import { AddressDto } from './address.dto';
|
||||
|
||||
export class WaypointDto extends AddressDto {
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
position?: number;
|
||||
position: number;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { hasValidPositionIndexes } from '@modules/matcher/interface/grpc-controllers/dtos/validators/has-valid-position-indexes.validator';
|
||||
import { WaypointDto } from '@modules/matcher/interface/grpc-controllers/dtos/waypoint.dto';
|
||||
|
||||
describe('addresses position validator', () => {
|
||||
describe('Waypoint position validator', () => {
|
||||
const mockAddress1: WaypointDto = {
|
||||
position: 0,
|
||||
lon: 48.689445,
|
||||
lat: 6.17651,
|
||||
houseNumber: '5',
|
||||
|
@ -12,6 +13,7 @@ describe('addresses position validator', () => {
|
|||
country: 'France',
|
||||
};
|
||||
const mockAddress2: WaypointDto = {
|
||||
position: 1,
|
||||
lon: 48.8566,
|
||||
lat: 2.3522,
|
||||
locality: 'Paris',
|
||||
|
@ -19,45 +21,15 @@ describe('addresses position validator', () => {
|
|||
country: 'France',
|
||||
};
|
||||
const mockAddress3: WaypointDto = {
|
||||
position: 2,
|
||||
lon: 49.2628,
|
||||
lat: 4.0347,
|
||||
locality: 'Reims',
|
||||
postalCode: '51454',
|
||||
postalCode: '51000',
|
||||
country: 'France',
|
||||
};
|
||||
|
||||
it('should not validate if no position is defined', () => {
|
||||
expect(
|
||||
hasValidPositionIndexes([mockAddress1, mockAddress2, mockAddress3]),
|
||||
).toBeFalsy();
|
||||
});
|
||||
it('should not validate if only one position is defined', () => {
|
||||
mockAddress1.position = 0;
|
||||
expect(
|
||||
hasValidPositionIndexes([mockAddress1, mockAddress2, mockAddress3]),
|
||||
).toBeFalsy();
|
||||
});
|
||||
it('should not validate if positions are partially defined', () => {
|
||||
mockAddress1.position = 0;
|
||||
mockAddress2.position = null;
|
||||
mockAddress3.position = undefined;
|
||||
expect(
|
||||
hasValidPositionIndexes([mockAddress1, mockAddress2, mockAddress3]),
|
||||
).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not validate if multiple positions have same value', () => {
|
||||
mockAddress1.position = 0;
|
||||
mockAddress2.position = 1;
|
||||
mockAddress3.position = 1;
|
||||
expect(
|
||||
hasValidPositionIndexes([mockAddress1, mockAddress2, mockAddress3]),
|
||||
).toBeFalsy();
|
||||
});
|
||||
it('should validate if all positions are ordered', () => {
|
||||
mockAddress1.position = 0;
|
||||
mockAddress2.position = 1;
|
||||
mockAddress3.position = 2;
|
||||
it('should validate if positions are ordered', () => {
|
||||
expect(
|
||||
hasValidPositionIndexes([mockAddress1, mockAddress2, mockAddress3]),
|
||||
).toBeTruthy();
|
||||
|
@ -68,8 +40,23 @@ describe('addresses position validator', () => {
|
|||
hasValidPositionIndexes([mockAddress1, mockAddress2, mockAddress3]),
|
||||
).toBeTruthy();
|
||||
});
|
||||
it('should not validate if positions are not valid', () => {
|
||||
mockAddress1.position = 0;
|
||||
mockAddress2.position = 2;
|
||||
mockAddress3.position = 3;
|
||||
expect(
|
||||
hasValidPositionIndexes([mockAddress1, mockAddress2, mockAddress3]),
|
||||
).toBeFalsy();
|
||||
});
|
||||
it('should not validate if multiple positions have same value', () => {
|
||||
mockAddress1.position = 0;
|
||||
mockAddress2.position = 1;
|
||||
mockAddress3.position = 1;
|
||||
expect(
|
||||
hasValidPositionIndexes([mockAddress1, mockAddress2, mockAddress3]),
|
||||
).toBeFalsy();
|
||||
});
|
||||
it('should not validate if no waypoints are defined', () => {
|
||||
expect(hasValidPositionIndexes(undefined)).toBeFalsy();
|
||||
expect(hasValidPositionIndexes([])).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
"baseUrl": "./",
|
||||
"incremental": true,
|
||||
"skipLibCheck": true,
|
||||
"strictNullChecks": false,
|
||||
"strictNullChecks": true,
|
||||
"noImplicitAny": false,
|
||||
"strictBindCallApply": false,
|
||||
"forceConsistentCasingInFileNames": false,
|
||||
|
|
Loading…
Reference in New Issue