use configuration package for georouter
This commit is contained in:
parent
c5bf6102e6
commit
8befcc3c80
40
.env.dist
40
.env.dist
|
@ -21,43 +21,3 @@ REDIS_MATCHING_TTL=900
|
|||
|
||||
# CACHE
|
||||
CACHE_TTL=5000
|
||||
|
||||
# DEFAULT CONFIGURATION
|
||||
|
||||
# algorithm type
|
||||
ALGORITHM=PASSENGER_ORIENTED
|
||||
# max distance in metres between driver
|
||||
# route and passenger pick-up / drop-off
|
||||
REMOTENESS=15000
|
||||
# use passenger proportion
|
||||
USE_PROPORTION=true
|
||||
# minimal driver proportion
|
||||
PROPORTION=0.3
|
||||
# use azimuth calculation
|
||||
USE_AZIMUTH=true
|
||||
# azimuth margin
|
||||
AZIMUTH_MARGIN=10
|
||||
# margin duration in seconds
|
||||
MARGIN_DURATION=900
|
||||
# default validity duration (in days) for recurrent proposals
|
||||
VALIDITY_DURATION=365
|
||||
# max detour ratio
|
||||
MAX_DETOUR_DISTANCE_RATIO=0.3
|
||||
MAX_DETOUR_DURATION_RATIO=0.3
|
||||
# gerouter type
|
||||
GEOROUTER_TYPE=graphhopper
|
||||
# georouter url
|
||||
GEOROUTER_URL=http://localhost:8989
|
||||
# default carpool departure time margin (in seconds)
|
||||
DEPARTURE_TIME_MARGIN=900
|
||||
# default role
|
||||
ROLE=passenger
|
||||
# seats proposes as driver / requested as passenger
|
||||
SEATS_PROPOSED=3
|
||||
SEATS_REQUESTED=1
|
||||
# accept only same frequency requests
|
||||
STRICT_FREQUENCY=false
|
||||
# default timezone
|
||||
TIMEZONE=Europe/Paris
|
||||
# number of matching results per page
|
||||
PER_PAGE=10
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
"dependencies": {
|
||||
"@grpc/grpc-js": "^1.9.9",
|
||||
"@grpc/proto-loader": "^0.7.10",
|
||||
"@mobicoop/configuration-module": "^7.1.0",
|
||||
"@mobicoop/configuration-module": "^7.2.1",
|
||||
"@mobicoop/ddd-library": "^2.1.1",
|
||||
"@mobicoop/health-module": "^2.3.1",
|
||||
"@mobicoop/message-broker-module": "^2.1.1",
|
||||
|
@ -1573,9 +1573,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@mobicoop/configuration-module": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@mobicoop/configuration-module/-/configuration-module-7.1.0.tgz",
|
||||
"integrity": "sha512-7AlfiTEntt1ZTqzCONMJ3hauaXaDpt44hUhKVkZNR6/54JfJCBb29nlEuZFXOwrVjuuoqjmaozRw/txlPmIbaA==",
|
||||
"version": "7.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@mobicoop/configuration-module/-/configuration-module-7.2.1.tgz",
|
||||
"integrity": "sha512-PGY80+uN33yKSxvqcR2CPlAbhEY67xYfVDqkphIoqGb5qAwioVZH5a8InJw4Zg0Q5bx0ZQG5pcK0jha7kSxqzQ==",
|
||||
"dependencies": {
|
||||
"@songkeys/nestjs-redis": "^10.0.0",
|
||||
"ioredis": "^5.3.2"
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
"@grpc/grpc-js": "^1.9.9",
|
||||
"@grpc/proto-loader": "^0.7.10",
|
||||
"@songkeys/nestjs-redis": "^10.0.0",
|
||||
"@mobicoop/configuration-module": "^7.1.0",
|
||||
"@mobicoop/configuration-module": "^7.2.1",
|
||||
"@mobicoop/ddd-library": "^2.1.1",
|
||||
"@mobicoop/health-module": "^2.3.1",
|
||||
"@mobicoop/message-broker-module": "^2.1.1",
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import {
|
||||
ConfigurationDomain,
|
||||
ConfigurationKey,
|
||||
ConfigurationDomainGet,
|
||||
ConfigurationType,
|
||||
} from '@mobicoop/configuration-module';
|
||||
|
||||
|
@ -10,33 +9,24 @@ export const CARPOOL_CONFIG_SEATS_REQUESTED = 'seatsRequested';
|
|||
export const CARPOOL_CONFIG_DEPARTURE_TIME_MARGIN = 'departureTimeMargin';
|
||||
export const CARPOOL_CONFIG_STRICT_FREQUENCY = 'strictFrequency';
|
||||
|
||||
export const CarpoolConfig: {
|
||||
domain: ConfigurationDomain;
|
||||
key: ConfigurationKey;
|
||||
type: ConfigurationType;
|
||||
}[] = [
|
||||
export const CarpoolConfig: ConfigurationDomainGet[] = [
|
||||
{
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: CARPOOL_CONFIG_ROLE,
|
||||
type: ConfigurationType.STRING,
|
||||
},
|
||||
{
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: CARPOOL_CONFIG_SEATS_PROPOSED,
|
||||
type: ConfigurationType.INT,
|
||||
},
|
||||
{
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: CARPOOL_CONFIG_SEATS_REQUESTED,
|
||||
type: ConfigurationType.INT,
|
||||
},
|
||||
{
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: CARPOOL_CONFIG_DEPARTURE_TIME_MARGIN,
|
||||
type: ConfigurationType.INT,
|
||||
},
|
||||
{
|
||||
domain: ConfigurationDomain.CARPOOL,
|
||||
key: CARPOOL_CONFIG_STRICT_FREQUENCY,
|
||||
type: ConfigurationType.BOOLEAN,
|
||||
},
|
||||
|
|
|
@ -39,7 +39,7 @@ import {
|
|||
MATCH_CONFIG_USE_AZIMUTH,
|
||||
MATCH_CONFIG_USE_PROPORTION,
|
||||
MatchConfig,
|
||||
PAGINATION_CONFG_PER_PAGE,
|
||||
PAGINATION_CONFIG_PER_PAGE,
|
||||
PaginationConfig,
|
||||
} from '@modules/ad/match.constants';
|
||||
|
||||
|
@ -112,7 +112,7 @@ export class MatchQueryHandler implements IQueryHandler {
|
|||
})
|
||||
.setDefaultPagination({
|
||||
page: 1,
|
||||
perPage: paginationConfigurator.get<number>(PAGINATION_CONFG_PER_PAGE),
|
||||
perPage: paginationConfigurator.get<number>(PAGINATION_CONFIG_PER_PAGE),
|
||||
})
|
||||
.setDatesAndSchedule(this.datetimeTransformer);
|
||||
let matchingEntity: MatchingEntity | undefined = await this._cachedMatching(
|
||||
|
|
|
@ -30,6 +30,8 @@ export class AdCreatedMessageHandler {
|
|||
waypoints: createdAd.waypoints,
|
||||
}),
|
||||
);
|
||||
} catch (e: any) {}
|
||||
} catch (e: any) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import {
|
||||
ConfigurationDomain,
|
||||
ConfigurationKey,
|
||||
ConfigurationDomainGet,
|
||||
ConfigurationType,
|
||||
} from '@mobicoop/configuration-module';
|
||||
|
||||
|
@ -12,63 +11,46 @@ export const MATCH_CONFIG_USE_AZIMUTH = 'useAzimuth';
|
|||
export const MATCH_CONFIG_AZIMUTH_MARGIN = 'azimuthMargin';
|
||||
export const MATCH_CONFIG_MAX_DETOUR_DISTANCE_RATIO = 'maxDetourDistanceRatio';
|
||||
export const MATCH_CONFIG_MAX_DETOUR_DURATION_RATIO = 'maxDetourDurationRatio';
|
||||
export const PAGINATION_CONFG_PER_PAGE = 'perPage';
|
||||
export const PAGINATION_CONFIG_PER_PAGE = 'perPage';
|
||||
|
||||
export const MatchConfig: {
|
||||
domain: ConfigurationDomain;
|
||||
key: ConfigurationKey;
|
||||
type: ConfigurationType;
|
||||
}[] = [
|
||||
export const MatchConfig: ConfigurationDomainGet[] = [
|
||||
{
|
||||
domain: ConfigurationDomain.MATCH,
|
||||
key: MATCH_CONFIG_ALGORITHM,
|
||||
type: ConfigurationType.STRING,
|
||||
},
|
||||
{
|
||||
domain: ConfigurationDomain.MATCH,
|
||||
key: MATCH_CONFIG_REMOTENESS,
|
||||
type: ConfigurationType.INT,
|
||||
},
|
||||
{
|
||||
domain: ConfigurationDomain.MATCH,
|
||||
key: MATCH_CONFIG_USE_PROPORTION,
|
||||
type: ConfigurationType.BOOLEAN,
|
||||
},
|
||||
{
|
||||
domain: ConfigurationDomain.MATCH,
|
||||
key: MATCH_CONFIG_PROPORTION,
|
||||
type: ConfigurationType.FLOAT,
|
||||
},
|
||||
{
|
||||
domain: ConfigurationDomain.MATCH,
|
||||
key: MATCH_CONFIG_USE_AZIMUTH,
|
||||
type: ConfigurationType.BOOLEAN,
|
||||
},
|
||||
{
|
||||
domain: ConfigurationDomain.MATCH,
|
||||
key: MATCH_CONFIG_AZIMUTH_MARGIN,
|
||||
type: ConfigurationType.INT,
|
||||
},
|
||||
{
|
||||
domain: ConfigurationDomain.MATCH,
|
||||
key: MATCH_CONFIG_MAX_DETOUR_DISTANCE_RATIO,
|
||||
type: ConfigurationType.FLOAT,
|
||||
},
|
||||
{
|
||||
domain: ConfigurationDomain.MATCH,
|
||||
key: MATCH_CONFIG_MAX_DETOUR_DURATION_RATIO,
|
||||
type: ConfigurationType.FLOAT,
|
||||
},
|
||||
];
|
||||
|
||||
export const PaginationConfig: {
|
||||
domain: ConfigurationDomain;
|
||||
key: ConfigurationKey;
|
||||
type: ConfigurationType;
|
||||
}[] = [
|
||||
export const PaginationConfig: ConfigurationDomainGet[] = [
|
||||
{
|
||||
domain: ConfigurationDomain.PAGINATION,
|
||||
key: PAGINATION_CONFG_PER_PAGE,
|
||||
key: PAGINATION_CONFIG_PER_PAGE,
|
||||
type: ConfigurationType.INT,
|
||||
},
|
||||
];
|
||||
|
|
|
@ -40,7 +40,7 @@ import {
|
|||
MATCH_CONFIG_REMOTENESS,
|
||||
MATCH_CONFIG_USE_AZIMUTH,
|
||||
MATCH_CONFIG_USE_PROPORTION,
|
||||
PAGINATION_CONFG_PER_PAGE,
|
||||
PAGINATION_CONFIG_PER_PAGE,
|
||||
} from '@modules/ad/match.constants';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
|
@ -335,7 +335,7 @@ const mockConfigurationRepository: GetConfigurationRepositoryPort = {
|
|||
return new Configurator(ConfigurationDomain.PAGINATION, [
|
||||
{
|
||||
domain: ConfigurationDomain.PAGINATION,
|
||||
key: PAGINATION_CONFG_PER_PAGE,
|
||||
key: PAGINATION_CONFIG_PER_PAGE,
|
||||
value: 10,
|
||||
},
|
||||
]);
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
import { DefaultParams } from '../types/default-params.type';
|
||||
|
||||
export interface DefaultParamsProviderPort {
|
||||
getParams(): DefaultParams;
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
export type DefaultParams = {
|
||||
GEOROUTER_TYPE?: string;
|
||||
GEOROUTER_URL?: string;
|
||||
};
|
|
@ -0,0 +1,18 @@
|
|||
import {
|
||||
ConfigurationDomainGet,
|
||||
ConfigurationType,
|
||||
} from '@mobicoop/configuration-module';
|
||||
|
||||
export const GEOGRAPHY_CONFIG_GEOROUTER_TYPE = 'georouterType';
|
||||
export const GEOGRAPHY_CONFIG_GEOROUTER_URL = 'georouterUrl';
|
||||
|
||||
export const GeographyConfig: ConfigurationDomainGet[] = [
|
||||
{
|
||||
key: GEOGRAPHY_CONFIG_GEOROUTER_TYPE,
|
||||
type: ConfigurationType.STRING,
|
||||
},
|
||||
{
|
||||
key: GEOGRAPHY_CONFIG_GEOROUTER_URL,
|
||||
type: ConfigurationType.STRING,
|
||||
},
|
||||
];
|
|
@ -2,3 +2,6 @@ export const PARAMS_PROVIDER = Symbol('PARAMS_PROVIDER');
|
|||
export const DIRECTION_ENCODER = Symbol('DIRECTION_ENCODER');
|
||||
export const GEOROUTER = Symbol('GEOROUTER');
|
||||
export const GEODESIC = Symbol('GEODESIC');
|
||||
export const GEOGRAPHY_CONFIGURATION_REPOSITORY = Symbol(
|
||||
'GEOGRAPHY_CONFIGURATION_REPOSITORY',
|
||||
);
|
||||
|
|
|
@ -3,10 +3,9 @@ import { CqrsModule } from '@nestjs/cqrs';
|
|||
import {
|
||||
DIRECTION_ENCODER,
|
||||
GEODESIC,
|
||||
GEOGRAPHY_CONFIGURATION_REPOSITORY,
|
||||
GEOROUTER,
|
||||
PARAMS_PROVIDER,
|
||||
} from './geography.di-tokens';
|
||||
import { DefaultParamsProvider } from './infrastructure/default-params-provider';
|
||||
import { PostgresDirectionEncoder } from './infrastructure/postgres-direction-encoder';
|
||||
import { GetBasicRouteController } from './interface/controllers/get-basic-route.controller';
|
||||
import { RouteMapper } from './route.mapper';
|
||||
|
@ -15,6 +14,7 @@ import { GraphhopperGeorouter } from './infrastructure/graphhopper-georouter';
|
|||
import { HttpModule } from '@nestjs/axios';
|
||||
import { GetRouteQueryHandler } from './core/application/queries/get-route/get-route.query-handler';
|
||||
import { GetDetailedRouteController } from './interface/controllers/get-detailed-route.controller';
|
||||
import { ConfigurationRepository } from '@mobicoop/configuration-module';
|
||||
|
||||
const queryHandlers: Provider[] = [GetRouteQueryHandler];
|
||||
|
||||
|
@ -22,8 +22,8 @@ const mappers: Provider[] = [RouteMapper];
|
|||
|
||||
const adapters: Provider[] = [
|
||||
{
|
||||
provide: PARAMS_PROVIDER,
|
||||
useClass: DefaultParamsProvider,
|
||||
provide: GEOGRAPHY_CONFIGURATION_REPOSITORY,
|
||||
useClass: ConfigurationRepository,
|
||||
},
|
||||
{
|
||||
provide: DIRECTION_ENCODER,
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { DefaultParamsProviderPort } from '../core/application/ports/default-params-provider.port';
|
||||
import { DefaultParams } from '../core/application/types/default-params.type';
|
||||
|
||||
@Injectable()
|
||||
export class DefaultParamsProvider implements DefaultParamsProviderPort {
|
||||
constructor(private readonly configService: ConfigService) {}
|
||||
getParams = (): DefaultParams => ({
|
||||
GEOROUTER_TYPE: this.configService.get('GEOROUTER_TYPE'),
|
||||
GEOROUTER_URL: this.configService.get('GEOROUTER_URL'),
|
||||
});
|
||||
}
|
|
@ -3,8 +3,10 @@ import { HttpService } from '@nestjs/axios';
|
|||
import { GeorouterPort } from '../core/application/ports/georouter.port';
|
||||
import { GeorouterSettings } from '../core/application/types/georouter-settings.type';
|
||||
import { Route, Step, Point } from '../core/domain/route.types';
|
||||
import { DefaultParamsProviderPort } from '../core/application/ports/default-params-provider.port';
|
||||
import { GEODESIC, PARAMS_PROVIDER } from '../geography.di-tokens';
|
||||
import {
|
||||
GEODESIC,
|
||||
GEOGRAPHY_CONFIGURATION_REPOSITORY,
|
||||
} from '../geography.di-tokens';
|
||||
import { catchError, lastValueFrom, map } from 'rxjs';
|
||||
import { AxiosError, AxiosResponse } from 'axios';
|
||||
import {
|
||||
|
@ -12,6 +14,15 @@ import {
|
|||
RouteNotFoundException,
|
||||
} from '../core/domain/route.errors';
|
||||
import { GeodesicPort } from '../core/application/ports/geodesic.port';
|
||||
import {
|
||||
ConfigurationDomain,
|
||||
Configurator,
|
||||
GetConfigurationRepositoryPort,
|
||||
} from '@mobicoop/configuration-module';
|
||||
import {
|
||||
GEOGRAPHY_CONFIG_GEOROUTER_URL,
|
||||
GeographyConfig,
|
||||
} from '../geography.constants';
|
||||
|
||||
@Injectable()
|
||||
export class GraphhopperGeorouter implements GeorouterPort {
|
||||
|
@ -20,20 +31,24 @@ export class GraphhopperGeorouter implements GeorouterPort {
|
|||
|
||||
constructor(
|
||||
private readonly httpService: HttpService,
|
||||
@Inject(PARAMS_PROVIDER)
|
||||
private readonly defaultParamsProvider: DefaultParamsProviderPort,
|
||||
@Inject(GEOGRAPHY_CONFIGURATION_REPOSITORY)
|
||||
private readonly configurationRepository: GetConfigurationRepositoryPort,
|
||||
@Inject(GEODESIC) private readonly geodesic: GeodesicPort,
|
||||
) {
|
||||
this.url = [
|
||||
defaultParamsProvider.getParams().GEOROUTER_URL,
|
||||
'/route?',
|
||||
].join('');
|
||||
}
|
||||
) {}
|
||||
|
||||
route = async (
|
||||
waypoints: Point[],
|
||||
settings: GeorouterSettings,
|
||||
): Promise<Route> => {
|
||||
const geographyConfigurator: Configurator =
|
||||
await this.configurationRepository.mget(
|
||||
ConfigurationDomain.GEOGRAPHY,
|
||||
GeographyConfig,
|
||||
);
|
||||
this.url = [
|
||||
geographyConfigurator.get<string>(GEOGRAPHY_CONFIG_GEOROUTER_URL),
|
||||
'/route?',
|
||||
].join('');
|
||||
this._setDefaultUrlArgs();
|
||||
this._setSettings(settings);
|
||||
return this._getRoute(waypoints);
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
import { DefaultParams } from '@modules/geography/core/application/types/default-params.type';
|
||||
import { DefaultParamsProvider } from '@modules/geography/infrastructure/default-params-provider';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
const mockConfigService = {
|
||||
get: jest.fn().mockImplementation((value: string) => {
|
||||
switch (value) {
|
||||
case 'GEOROUTER_TYPE':
|
||||
return 'graphhopper';
|
||||
case 'GEOROUTER_URL':
|
||||
return 'http://localhost:8989';
|
||||
default:
|
||||
return 'some_default_value';
|
||||
}
|
||||
}),
|
||||
};
|
||||
|
||||
describe('DefaultParamsProvider', () => {
|
||||
let defaultParamsProvider: DefaultParamsProvider;
|
||||
|
||||
beforeAll(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
imports: [],
|
||||
providers: [
|
||||
DefaultParamsProvider,
|
||||
{
|
||||
provide: ConfigService,
|
||||
useValue: mockConfigService,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
defaultParamsProvider = module.get<DefaultParamsProvider>(
|
||||
DefaultParamsProvider,
|
||||
);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(defaultParamsProvider).toBeDefined();
|
||||
});
|
||||
|
||||
it('should provide default params', async () => {
|
||||
const params: DefaultParams = defaultParamsProvider.getParams();
|
||||
expect(params.GEOROUTER_TYPE).toBe('graphhopper');
|
||||
expect(params.GEOROUTER_URL).toBe('http://localhost:8989');
|
||||
});
|
||||
});
|
|
@ -1,13 +1,19 @@
|
|||
import { DefaultParamsProviderPort } from '@modules/geography/core/application/ports/default-params-provider.port';
|
||||
import {
|
||||
ConfigurationDomain,
|
||||
ConfigurationDomainGet,
|
||||
Configurator,
|
||||
GetConfigurationRepositoryPort,
|
||||
} from '@mobicoop/configuration-module';
|
||||
import { GeodesicPort } from '@modules/geography/core/application/ports/geodesic.port';
|
||||
import {
|
||||
GeorouterUnavailableException,
|
||||
RouteNotFoundException,
|
||||
} from '@modules/geography/core/domain/route.errors';
|
||||
import { Route, Step } from '@modules/geography/core/domain/route.types';
|
||||
import { GEOGRAPHY_CONFIG_GEOROUTER_URL } from '@modules/geography/geography.constants';
|
||||
import {
|
||||
GEODESIC,
|
||||
PARAMS_PROVIDER,
|
||||
GEOGRAPHY_CONFIGURATION_REPOSITORY,
|
||||
} from '@modules/geography/geography.di-tokens';
|
||||
import { GraphhopperGeorouter } from '@modules/geography/infrastructure/graphhopper-georouter';
|
||||
import { HttpService } from '@nestjs/axios';
|
||||
|
@ -262,10 +268,23 @@ const mockGeodesic: GeodesicPort = {
|
|||
distance: jest.fn().mockImplementation(() => 50000),
|
||||
};
|
||||
|
||||
const mockDefaultParamsProvider: DefaultParamsProviderPort = {
|
||||
getParams: jest.fn().mockImplementation(() => ({
|
||||
GEOROUTER_URL: 'http://localhost:8989',
|
||||
})),
|
||||
const mockConfigurationRepository: GetConfigurationRepositoryPort = {
|
||||
get: jest.fn(),
|
||||
mget: jest.fn().mockImplementation(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
(domain: ConfigurationDomain, configs: ConfigurationDomainGet[]) => {
|
||||
switch (domain) {
|
||||
case ConfigurationDomain.GEOGRAPHY:
|
||||
return new Configurator(ConfigurationDomain.GEOGRAPHY, [
|
||||
{
|
||||
domain: ConfigurationDomain.GEOGRAPHY,
|
||||
key: GEOGRAPHY_CONFIG_GEOROUTER_URL,
|
||||
value: 'http://localhost:8989',
|
||||
},
|
||||
]);
|
||||
}
|
||||
},
|
||||
),
|
||||
};
|
||||
|
||||
describe('Graphhopper Georouter', () => {
|
||||
|
@ -281,8 +300,8 @@ describe('Graphhopper Georouter', () => {
|
|||
useValue: mockHttpService,
|
||||
},
|
||||
{
|
||||
provide: PARAMS_PROVIDER,
|
||||
useValue: mockDefaultParamsProvider,
|
||||
provide: GEOGRAPHY_CONFIGURATION_REPOSITORY,
|
||||
useValue: mockConfigurationRepository,
|
||||
},
|
||||
{
|
||||
provide: GEODESIC,
|
||||
|
|
Loading…
Reference in New Issue