Compare commits
45 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
bf542b2738 | |
|
|
ed8762844e | |
|
|
1d153a7b89 | |
|
|
88092be0fb | |
|
|
9c4c697c7e | |
|
|
d75ac96384 | |
|
|
9f65699bce | |
|
|
4305368c29 | |
|
|
e65cc4dad8 | |
|
|
861aab8d96 | |
|
|
834c2f4d9e | |
|
|
d72fbff94b | |
|
|
a0757adc7d | |
|
|
6e6ac8d84a | |
|
|
b38a260032 | |
|
|
42e1c854b0 | |
|
|
5a5f1172a4 | |
|
|
d4ce7b4af1 | |
|
|
cdf413593b | |
|
|
ac5212187d | |
|
|
cb32f99ade | |
|
|
b88ac36b30 | |
|
|
05a992ce7c | |
|
|
f39b75af5b | |
|
|
163977b3ed | |
|
|
4f616e8ddc | |
|
|
d7b1578611 | |
|
|
41ed0fcec7 | |
|
|
b0d9fad619 | |
|
|
7dcc965f4d | |
|
|
1bd50b7642 | |
|
|
b33cf3b041 | |
|
|
5eb088dc94 | |
|
|
6e7117e772 | |
|
|
f54eca303b | |
|
|
b7e981d1ba | |
|
|
d836c5d6b1 | |
|
|
5b43429d8d | |
|
|
de0f91024d | |
|
|
dbda93a1ba | |
|
|
c0122e395a | |
|
|
575041eff0 | |
|
|
84e99adeda | |
|
|
a6a69c5051 | |
|
|
f7de60fafe |
60
.env.dist
60
.env.dist
|
|
@ -4,7 +4,7 @@ SERVICE_PORT=5003
|
||||||
HEALTH_SERVICE_PORT=6003
|
HEALTH_SERVICE_PORT=6003
|
||||||
|
|
||||||
# MESSAGE BROKER
|
# MESSAGE BROKER
|
||||||
MESSAGE_BROKER_URI=amqp://v3-broker:5672
|
MESSAGE_BROKER_URI=amqp://mobicoop:mobicoop@v3-broker:5672
|
||||||
MESSAGE_BROKER_EXCHANGE=mobicoop
|
MESSAGE_BROKER_EXCHANGE=mobicoop
|
||||||
MESSAGE_BROKER_EXCHANGE_DURABILITY=true
|
MESSAGE_BROKER_EXCHANGE_DURABILITY=true
|
||||||
|
|
||||||
|
|
@ -15,9 +15,15 @@ REDIS_PORT=6379
|
||||||
|
|
||||||
# DEFAULT CONFIGURATION
|
# DEFAULT CONFIGURATION
|
||||||
|
|
||||||
|
# AUTH
|
||||||
|
# encryption algorithm : BCRYPT / ARGON2I / ARGON2D / ARGON2ID
|
||||||
|
ENCRYPTION_ALGORITHM=ARGON2ID
|
||||||
|
|
||||||
# CARPOOL
|
# CARPOOL
|
||||||
# default carpool departure time margin (in seconds)
|
# default carpool departure time margin (in seconds)
|
||||||
DEPARTURE_TIME_MARGIN=900
|
DEPARTURE_TIME_MARGIN=900
|
||||||
|
# default validity duration (in days) for recurrent ads
|
||||||
|
RECURRENT_AD_VALIDITY_DURATION=365
|
||||||
# default role
|
# default role
|
||||||
ROLE=passenger
|
ROLE=passenger
|
||||||
# seats proposed as driver / requested as passenger
|
# seats proposed as driver / requested as passenger
|
||||||
|
|
@ -26,6 +32,58 @@ SEATS_REQUESTED=1
|
||||||
# accept only same frequency requests
|
# accept only same frequency requests
|
||||||
STRICT_FREQUENCY=false
|
STRICT_FREQUENCY=false
|
||||||
|
|
||||||
|
# MATCH
|
||||||
|
# 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
|
||||||
|
# max detour ratio
|
||||||
|
MAX_DETOUR_DISTANCE_RATIO=0.3
|
||||||
|
MAX_DETOUR_DURATION_RATIO=0.3
|
||||||
|
|
||||||
|
# GEOROUTER
|
||||||
|
GEOROUTER_TYPE=graphhopper
|
||||||
|
GEOROUTER_URL=http://localhost:8989
|
||||||
|
|
||||||
|
# GEOCODER
|
||||||
|
# default language
|
||||||
|
GEOCODER_LANG=fr
|
||||||
|
# minimal score to consider a result as valid
|
||||||
|
GEOCODER_MIN_CONFIDENCE=0.5
|
||||||
|
# max number of results per provider (input results)
|
||||||
|
GEOCODER_MAX_RESULTS_PER_PROVIDER=5
|
||||||
|
# max number of results per address type (output results)
|
||||||
|
GEOCODER_MAX_RESULTS_PER_TYPE=5
|
||||||
|
# sanitize results ?
|
||||||
|
GEOCODER_SANITIZE=true
|
||||||
|
# consolidate results ?
|
||||||
|
GEOCODER_CONSOLIDATE=true
|
||||||
|
# max distance in metres between 2 points to consider a duplicate
|
||||||
|
GEOCODER_PROXIMITY=5000
|
||||||
|
# population vs distance prioritizer coef
|
||||||
|
# "boost" population weight for results with a short distance
|
||||||
|
# => multiply the population by COEF / distance (in km)
|
||||||
|
GEOCODER_POPULATION_PRIORITIZER_COEF=100
|
||||||
|
# a json array for main providers, see Geocoder service for detail about the providers
|
||||||
|
GEOCODER_PROVIDERS='[{"name":"provider1","type":"providerType","baseUrl":"http://localhost","countryRestriction":"countryRestrictionString"}]'
|
||||||
|
# a json array for fallback providers
|
||||||
|
GEOCODER_PROVIDERS_FALLBACK='[{"name":"provider1","type":"providerType","apiKey":"anApiKey"}]'
|
||||||
|
# a json array for prioritizers, see Geocoder service for detail about the prioritizers
|
||||||
|
GEOCODER_PRIORITIZERS='[{"country": "countryName","addressTypes":[{"type":"addressType","prioritizers":[{"position":0,"name":"prioritizerName1"}]}]}]'
|
||||||
|
# a json array for consolidators, see Geocoder service for detail about the consolidators
|
||||||
|
GEOCODER_CONSOLIDATORS='[{"country":"countryName","addressTypes":[{"type":"addressType","name":"consolidatorName"}]}]'
|
||||||
|
|
||||||
# PAGINATION
|
# PAGINATION
|
||||||
# number of results per page
|
# number of results per page
|
||||||
PER_PAGE=10
|
PER_PAGE=10
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,10 @@ stages:
|
||||||
- test
|
- test
|
||||||
- build
|
- build
|
||||||
|
|
||||||
|
include:
|
||||||
|
- template: Security/SAST.gitlab-ci.yml
|
||||||
|
- template: Security/Secret-Detection.gitlab-ci.yml
|
||||||
|
|
||||||
##############
|
##############
|
||||||
# TEST STAGE #
|
# TEST STAGE #
|
||||||
##############
|
##############
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
_Replace italic text by your own description_
|
||||||
|
|
||||||
|
## Feature Merge Request
|
||||||
|
|
||||||
|
### Why this Merge Request
|
||||||
|
|
||||||
|
_This merge request addresses, and describe the problem or user story being addressed._
|
||||||
|
|
||||||
|
### What is implemented, what is the chosen solution
|
||||||
|
|
||||||
|
_Explain the fix or solution implemented. Which other solution have been envisaged._
|
||||||
|
|
||||||
|
### Related issues and impact on other project in codebase
|
||||||
|
|
||||||
|
_Provide links to the related issues, feature requests and merge request (from Gitlab and Redmine)._
|
||||||
|
|
||||||
|
_And Link to other project Impacted._
|
||||||
|
|
||||||
|
### Other Information
|
||||||
|
|
||||||
|
_Include any extra information or considerations for reviewers._
|
||||||
|
|
||||||
|
## Checklists
|
||||||
|
|
||||||
|
### Merge Request
|
||||||
|
|
||||||
|
- [ ] Target branch identified.
|
||||||
|
- [ ] Code based on last version of target branch.
|
||||||
|
- [ ] Description filled.
|
||||||
|
- [ ] Impact on other project codebase identified.
|
||||||
|
- [ ] Documentation reflects the changes made.
|
||||||
|
- [ ] Test run in gitlab pipeline and locally.
|
||||||
|
- [ ] One or more reviewer is defined
|
||||||
|
|
||||||
|
### Code Review
|
||||||
|
|
||||||
|
- [ ] Code follows project coding guidelines.
|
||||||
|
- [ ] Code follows project designed architecture.
|
||||||
|
- [ ] Code is easily readable.
|
||||||
|
- [ ] Everything new have an explicit and pertinent name (variable, method, file ...)
|
||||||
|
- [ ] No redundant/duplicate code (unless explain by architecture choice)
|
||||||
|
- [ ] Commit are all related to MR and well written (Atomic commit).
|
||||||
|
- [ ] New code is tested and covered by automated test.
|
||||||
|
- [ ] No useless logging or debugging code.
|
||||||
|
- [ ] No code can be replaced by library or framework code.
|
||||||
|
|
||||||
|
### TODO before merge
|
||||||
|
|
||||||
|
- [ ] _add any task here_
|
||||||
|
- [ ] ...
|
||||||
|
|
||||||
|
### TODO after merge
|
||||||
|
|
||||||
|
- [ ] _add any task here_
|
||||||
|
- [ ] ...
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
_Replace italic text by your own description_
|
||||||
|
|
||||||
|
## Release Merge Request
|
||||||
|
|
||||||
|
### Why this Merge Request
|
||||||
|
|
||||||
|
_This merge request addresses, and describe the problem or user story being addressed._
|
||||||
|
|
||||||
|
### What is implemented, what is the chosen solution
|
||||||
|
|
||||||
|
_Explain the fix or solution implemented. Which other solution have been envisaged._
|
||||||
|
|
||||||
|
### Related issues and impact on other project in codebase
|
||||||
|
|
||||||
|
_Provide links to the related issues, feature requests and merge request (from Gitlab and Redmine)._
|
||||||
|
|
||||||
|
_And Link to other project Impacted._
|
||||||
|
|
||||||
|
### Other Information
|
||||||
|
|
||||||
|
_Include any extra information or considerations for reviewers._
|
||||||
|
|
||||||
|
## Checklists
|
||||||
|
|
||||||
|
### Merge Request
|
||||||
|
|
||||||
|
- [ ] Target branch identified.
|
||||||
|
- [ ] Code based on last version of target branch.
|
||||||
|
- [ ] Description filled.
|
||||||
|
- [ ] Impact on other project codebase identified.
|
||||||
|
- [ ] Documentation reflects the changes made.
|
||||||
|
- [ ] Test run in gitlab pipeline and locally.
|
||||||
|
- [ ] One or more reviewer is defined
|
||||||
|
|
||||||
|
### Code Review
|
||||||
|
|
||||||
|
- [ ] Code follows project coding guidelines.
|
||||||
|
- [ ] Code follows project designed architecture.
|
||||||
|
- [ ] Code is easily readable.
|
||||||
|
- [ ] Everything new have an explicit and pertinent name (variable, method, file ...)
|
||||||
|
- [ ] No redundant/duplicate code (unless explain by architecture choice)
|
||||||
|
- [ ] Commit are all related to MR and well written (Atomic commit).
|
||||||
|
- [ ] New code is tested and covered by automated test.
|
||||||
|
- [ ] No useless logging or debugging code.
|
||||||
|
- [ ] No code can be replaced by library or framework code.
|
||||||
|
|
||||||
|
### Change Management
|
||||||
|
|
||||||
|
- [ ] Release is planned
|
||||||
|
- [ ] Merge Request to be included are identified
|
||||||
|
- [ ] Concerned Team are aware of the change
|
||||||
|
- [ ] No other change on the same day (if possible)
|
||||||
|
|
||||||
|
### TODO before merge
|
||||||
|
|
||||||
|
- [ ] _add any task here_
|
||||||
|
- [ ] ...
|
||||||
|
|
||||||
|
### TODO after merge
|
||||||
|
|
||||||
|
- [ ] _add any task here_
|
||||||
|
- [ ] ...
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
_Replace italic text by your own description_
|
||||||
|
|
||||||
|
## Small Fix Merge Request
|
||||||
|
|
||||||
|
### Why this Merge Request
|
||||||
|
|
||||||
|
_This merge request addresses, and describe the problem or user story being addressed._
|
||||||
|
|
||||||
|
### What is implemented, what is the chosen solution
|
||||||
|
|
||||||
|
_Explain the fix or solution implemented. Which other solution have been envisaged._
|
||||||
|
|
||||||
|
### Related issues and impact on other project in codebase
|
||||||
|
|
||||||
|
_Provide links to the related issues, feature requests and merge request (from Gitlab and Redmine)._
|
||||||
|
|
||||||
|
_And Link to other project Impacted._
|
||||||
|
|
||||||
|
### Other Information
|
||||||
|
|
||||||
|
_Include any extra information or considerations for reviewers._
|
||||||
|
|
||||||
|
## Checklists
|
||||||
|
|
||||||
|
### Merge Request
|
||||||
|
|
||||||
|
- [ ] Target branch identified.
|
||||||
|
- [ ] Code based on last version of target branch.
|
||||||
|
- [ ] Description filled.
|
||||||
|
- [ ] Impact on other project codebase identified.
|
||||||
|
- [ ] Test run in gitlab pipeline and locally.
|
||||||
|
|
||||||
|
### Code Review
|
||||||
|
|
||||||
|
- [ ] Code is easily readable.
|
||||||
|
- [ ] Commit are all related to MR and well written (Atomic commit).
|
||||||
|
- [ ] No useless logging or debugging code.
|
||||||
|
|
@ -4,3 +4,4 @@ node_modules
|
||||||
dist
|
dist
|
||||||
coverage
|
coverage
|
||||||
.prettierrc.json
|
.prettierrc.json
|
||||||
|
.gitlab
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
# BUILD FOR LOCAL DEVELOPMENT
|
# BUILD FOR LOCAL DEVELOPMENT
|
||||||
###################
|
###################
|
||||||
|
|
||||||
FROM node:18-alpine3.16 As development
|
FROM docker.io/node:lts-hydrogen As development
|
||||||
|
|
||||||
# Create app directory
|
# Create app directory
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
|
|
@ -25,7 +25,7 @@ USER node
|
||||||
# BUILD FOR PRODUCTION
|
# BUILD FOR PRODUCTION
|
||||||
###################
|
###################
|
||||||
|
|
||||||
FROM node:18-alpine3.16 As build
|
FROM docker.io/node:lts-hydrogen As build
|
||||||
|
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
|
@ -56,7 +56,7 @@ USER node
|
||||||
# PRODUCTION
|
# PRODUCTION
|
||||||
###################
|
###################
|
||||||
|
|
||||||
FROM node:18-alpine3.16 As production
|
FROM docker.io/node:lts-hydrogen As production
|
||||||
|
|
||||||
# Copy package.json to be able to execute migration command
|
# Copy package.json to be able to execute migration command
|
||||||
COPY --chown=node:node package*.json ./
|
COPY --chown=node:node package*.json ./
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ Redis database is automatically populated at the start of the service. If keys a
|
||||||
|
|
||||||
The app exposes the following [gRPC](https://grpc.io/) services :
|
The app exposes the following [gRPC](https://grpc.io/) services :
|
||||||
|
|
||||||
- **Get** : get a configuration item by its domain and key
|
- **Get** : get a configuration item by its domain and key (retrieves the domain, key, value and type)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,5 @@ SERVICE_URL=0.0.0.0
|
||||||
SERVICE_PORT=5003
|
SERVICE_PORT=5003
|
||||||
|
|
||||||
# REDIS
|
# REDIS
|
||||||
REDIS_IMAGE=redis:7.0-alpine
|
REDIS_IMAGE=docker.io/redis:7.0-alpine
|
||||||
REDIS_PASSWORD=redis
|
REDIS_PASSWORD=redis
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
# BUILD FOR CI TESTING
|
# BUILD FOR CI TESTING
|
||||||
###################
|
###################
|
||||||
|
|
||||||
FROM node:18-alpine3.16
|
FROM docker.io/node:lts-hydrogen
|
||||||
|
|
||||||
# Create app directory
|
# Create app directory
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
58
package.json
58
package.json
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@mobicoop/configuration",
|
"name": "@mobicoop/configuration",
|
||||||
"version": "2.3.0",
|
"version": "2.8.0",
|
||||||
"description": "Mobicoop V3 Configuration Service",
|
"description": "Mobicoop V3 Configuration Service",
|
||||||
"author": "sbriat",
|
"author": "sbriat",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|
@ -24,48 +24,48 @@
|
||||||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@grpc/grpc-js": "^1.9.8",
|
"@grpc/grpc-js": "^1.9.13",
|
||||||
"@grpc/proto-loader": "^0.7.10",
|
"@grpc/proto-loader": "^0.7.10",
|
||||||
"@mobicoop/configuration-module": "^6.1.0",
|
"@mobicoop/configuration-module": "^8.1.2",
|
||||||
"@mobicoop/ddd-library": "^2.1.1",
|
"@mobicoop/ddd-library": "^2.4.2",
|
||||||
"@mobicoop/health-module": "^2.3.1",
|
"@mobicoop/health-module": "^2.3.1",
|
||||||
"@mobicoop/message-broker-module": "^2.1.1",
|
"@mobicoop/message-broker-module": "^2.1.1",
|
||||||
"@nestjs/common": "^10.2.7",
|
"@nestjs/common": "^10.3.0",
|
||||||
"@nestjs/config": "^3.1.1",
|
"@nestjs/config": "^3.1.1",
|
||||||
"@nestjs/core": "^10.2.7",
|
"@nestjs/core": "^10.3.0",
|
||||||
"@nestjs/cqrs": "^10.2.6",
|
"@nestjs/cqrs": "^10.2.6",
|
||||||
"@nestjs/event-emitter": "^2.0.2",
|
"@nestjs/event-emitter": "^2.0.3",
|
||||||
"@nestjs/microservices": "^10.2.7",
|
"@nestjs/microservices": "^10.3.0",
|
||||||
"@nestjs/platform-express": "^10.2.7",
|
"@nestjs/platform-express": "^10.3.0",
|
||||||
"@nestjs/terminus": "^10.1.1",
|
"@nestjs/terminus": "^10.2.0",
|
||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.0",
|
"class-validator": "^0.14.1",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.12",
|
||||||
"rimraf": "^5.0.5"
|
"rimraf": "^5.0.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nestjs/cli": "^10.2.1",
|
"@nestjs/cli": "^10.3.0",
|
||||||
"@nestjs/schematics": "^10.0.3",
|
"@nestjs/schematics": "^10.1.0",
|
||||||
"@nestjs/testing": "^10.2.7",
|
"@nestjs/testing": "^10.3.0",
|
||||||
"@types/express": "^4.17.20",
|
"@types/express": "^4.17.21",
|
||||||
"@types/jest": "29.5.6",
|
"@types/jest": "29.5.11",
|
||||||
"@types/node": "^20.8.9",
|
"@types/node": "^20.11.2",
|
||||||
"@types/supertest": "^2.0.15",
|
"@types/supertest": "^6.0.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.9.0",
|
"@typescript-eslint/eslint-plugin": "^6.18.1",
|
||||||
"@typescript-eslint/parser": "^6.9.0",
|
"@typescript-eslint/parser": "^6.18.1",
|
||||||
"dotenv-cli": "^7.3.0",
|
"dotenv-cli": "^7.3.0",
|
||||||
"eslint": "^8.52.0",
|
"eslint": "^8.56.0",
|
||||||
"eslint-config-prettier": "^9.0.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-prettier": "^5.0.1",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"jest": "29.7.0",
|
"jest": "29.7.0",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.2.2",
|
||||||
"source-map-support": "^0.5.21",
|
"source-map-support": "^0.5.21",
|
||||||
"supertest": "^6.3.3",
|
"supertest": "^6.3.4",
|
||||||
"ts-jest": "29.1.1",
|
"ts-jest": "29.1.1",
|
||||||
"ts-loader": "^9.5.0",
|
"ts-loader": "^9.5.1",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.2",
|
||||||
"tsconfig-paths": "4.2.0",
|
"tsconfig-paths": "4.2.0",
|
||||||
"typescript": "^5.2.2"
|
"typescript": "^5.3.3"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"moduleFileExtensions": [
|
"moduleFileExtensions": [
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,20 @@ import paginationConfig from './config/pagination.config';
|
||||||
import serviceConfig from './config/service.config';
|
import serviceConfig from './config/service.config';
|
||||||
import redisConfig from './config/redis.config';
|
import redisConfig from './config/redis.config';
|
||||||
import { Transport } from '@nestjs/microservices';
|
import { Transport } from '@nestjs/microservices';
|
||||||
|
import matchConfig from './config/match.config';
|
||||||
|
import geographyConfig from './config/geography.config';
|
||||||
|
import authConfig from './config/auth.config';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule.forRoot({
|
ConfigModule.forRoot({
|
||||||
isGlobal: true,
|
isGlobal: true,
|
||||||
load: [
|
load: [
|
||||||
|
authConfig,
|
||||||
brokerConfig,
|
brokerConfig,
|
||||||
carpoolConfig,
|
carpoolConfig,
|
||||||
|
geographyConfig,
|
||||||
|
matchConfig,
|
||||||
paginationConfig,
|
paginationConfig,
|
||||||
redisConfig,
|
redisConfig,
|
||||||
serviceConfig,
|
serviceConfig,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
import { Config } from './config';
|
||||||
|
|
||||||
|
export interface AuthConfig extends Config {
|
||||||
|
encryptionAlgorithm: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default registerAs('auth', () => ({
|
||||||
|
encryptionAlgorithm: process.env.ENCRYPTION_ALGORITHM ?? 'ARGON2ID',
|
||||||
|
}));
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import { registerAs } from '@nestjs/config';
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
export default registerAs('broker', () => ({
|
export default registerAs('broker', () => ({
|
||||||
uri: process.env.MESSAGE_BROKER_URI ?? 'amqp://v3-broker:5672',
|
uri:
|
||||||
|
process.env.MESSAGE_BROKER_URI ?? 'amqp://mobicoop:mobicoop@v3-broker:5672',
|
||||||
exchange: process.env.MESSAGE_BROKER_EXCHANGE ?? 'mobicoop',
|
exchange: process.env.MESSAGE_BROKER_EXCHANGE ?? 'mobicoop',
|
||||||
durability: process.env.MESSAGE_BROKER_EXCHANGE_DURABILITY
|
durability: process.env.MESSAGE_BROKER_EXCHANGE_DURABILITY
|
||||||
? process.env.MESSAGE_BROKER_EXCHANGE_DURABILITY === 'false'
|
? process.env.MESSAGE_BROKER_EXCHANGE_DURABILITY === 'false'
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { ConfigurationDomain } from '@mobicoop/configuration-module';
|
import { Domain } from '@mobicoop/configuration-module';
|
||||||
|
|
||||||
export interface Config {
|
export interface Config {
|
||||||
domain: ConfigurationDomain;
|
domain: Domain;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
import { Config } from './config';
|
||||||
|
|
||||||
|
export interface GeographyConfig extends Config {
|
||||||
|
georouterType: string;
|
||||||
|
georouterUrl: string;
|
||||||
|
geocoderLang: string;
|
||||||
|
geocoderMinConfidence: number;
|
||||||
|
geocoderMaxResultsPerProvider: number;
|
||||||
|
geocoderMaxResultsPerType: number;
|
||||||
|
geocoderSanitize: boolean;
|
||||||
|
geocoderConsolidate: boolean;
|
||||||
|
geocoderProximity: number;
|
||||||
|
geocoderPopulationPrioritizerCoef: number;
|
||||||
|
geocoderProviders: object[];
|
||||||
|
geocoderProvidersFallback: object[];
|
||||||
|
geocoderPrioritizers: object[];
|
||||||
|
geocoderConsolidators: object[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default registerAs('geography', () => ({
|
||||||
|
georouterType: process.env.GEOROUTER_TYPE ?? 'graphhopper',
|
||||||
|
georouterUrl: process.env.GEOROUTER_URL ?? 'http://localhost:8989',
|
||||||
|
geocoderLang: process.env.GEOCODER_LANG ?? 'fr',
|
||||||
|
geocoderMinConfidence: process.env.GEOCODER_MIN_CONFIDENCE
|
||||||
|
? parseFloat(process.env.GEOCODER_MIN_CONFIDENCE)
|
||||||
|
: 0.5,
|
||||||
|
geocoderMaxResultsPerProvider: process.env.GEOCODER_MAX_RESULTS_PER_PROVIDER
|
||||||
|
? parseInt(process.env.GEOCODER_MAX_RESULTS_PER_PROVIDER)
|
||||||
|
: 5,
|
||||||
|
geocoderMaxResultsPerType: process.env.GEOCODER_MAX_RESULTS_PER_TYPE
|
||||||
|
? parseInt(process.env.GEOCODER_MAX_RESULTS_PER_TYPE)
|
||||||
|
: 5,
|
||||||
|
geocoderSanitize: process.env.GEOCODER_SANITIZE
|
||||||
|
? process.env.GEOCODER_SANITIZE === 'false'
|
||||||
|
? false
|
||||||
|
: true
|
||||||
|
: true,
|
||||||
|
geocoderConsolidate: process.env.GEOCODER_CONSOLIDATE
|
||||||
|
? process.env.GEOCODER_CONSOLIDATE === 'false'
|
||||||
|
? false
|
||||||
|
: true
|
||||||
|
: true,
|
||||||
|
geocoderProximity: process.env.GEOCODER_PROXIMITY
|
||||||
|
? parseInt(process.env.GEOCODER_PROXIMITY)
|
||||||
|
: 5000,
|
||||||
|
geocoderPopulationPrioritizerCoef: process.env
|
||||||
|
.GEOCODER_POPULATION_PRIORITIZER_COEF
|
||||||
|
? parseInt(process.env.GEOCODER_POPULATION_PRIORITIZER_COEF)
|
||||||
|
: 100,
|
||||||
|
geocoderProviders: process.env.GEOCODER_PROVIDERS
|
||||||
|
? JSON.parse(process.env.GEOCODER_PROVIDERS)
|
||||||
|
: [],
|
||||||
|
geocoderProvidersFallback: process.env.GEOCODER_PROVIDERS_FALLBACK
|
||||||
|
? JSON.parse(process.env.GEOCODER_PROVIDERS_FALLBACK)
|
||||||
|
: [],
|
||||||
|
geocoderPrioritizers: process.env.GEOCODER_PRIORITIZERS
|
||||||
|
? JSON.parse(process.env.GEOCODER_PRIORITIZERS)
|
||||||
|
: [],
|
||||||
|
geocoderConsolidators: process.env.GEOCODER_CONSOLIDATORS
|
||||||
|
? JSON.parse(process.env.GEOCODER_CONSOLIDATORS)
|
||||||
|
: [],
|
||||||
|
}));
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { ConfigurationResponseDto } from './interface/dtos/configuration.response.dto';
|
import { ConfigurationResponseDto } from './interface/dtos/configuration.response.dto';
|
||||||
import {
|
import { Identifier, Value } from '@mobicoop/configuration-module';
|
||||||
ConfigurationIdentifier,
|
|
||||||
ConfigurationValue,
|
|
||||||
} from '@mobicoop/configuration-module';
|
|
||||||
import { ConfigurationsManagerService } from './core/application/services/configurations-manager.service';
|
import { ConfigurationsManagerService } from './core/application/services/configurations-manager.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|
@ -13,15 +10,14 @@ export class ConfigurationMapper {
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
toResponse = (
|
toResponse = (
|
||||||
configurationIdentifier: ConfigurationIdentifier,
|
identifier: Identifier,
|
||||||
configurationValue: ConfigurationValue,
|
value: Value,
|
||||||
): ConfigurationResponseDto => {
|
): ConfigurationResponseDto => {
|
||||||
const response = new ConfigurationResponseDto();
|
const response = new ConfigurationResponseDto();
|
||||||
response.domain = configurationIdentifier.domain;
|
response.domain = identifier.domain;
|
||||||
response.key = configurationIdentifier.key;
|
response.key = identifier.key;
|
||||||
response.value = configurationValue;
|
response.value = typeof value === 'object' ? JSON.stringify(value) : value;
|
||||||
response.type =
|
response.type = this.configurationsManager.configurationType(value);
|
||||||
this.configurationsManager.configurationType(configurationValue);
|
|
||||||
return response;
|
return response;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import { ConfigurationIdentifier } from '@mobicoop/configuration-module';
|
import { Identifier } from '@mobicoop/configuration-module';
|
||||||
import { Command, CommandProps } from '@mobicoop/ddd-library';
|
import { Command, CommandProps } from '@mobicoop/ddd-library';
|
||||||
|
|
||||||
export class SetConfigurationCommand extends Command {
|
export class SetConfigurationCommand extends Command {
|
||||||
readonly configurationIdentifier: ConfigurationIdentifier;
|
readonly identifier: Identifier;
|
||||||
readonly value: string | boolean | number;
|
readonly value: string | boolean | number;
|
||||||
|
|
||||||
constructor(props: CommandProps<SetConfigurationCommand>) {
|
constructor(props: CommandProps<SetConfigurationCommand>) {
|
||||||
super(props);
|
super(props);
|
||||||
this.configurationIdentifier = props.configurationIdentifier;
|
this.identifier = props.identifier;
|
||||||
this.value = props.value;
|
this.value = props.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ import { Inject } from '@nestjs/common';
|
||||||
import { SetConfigurationCommand } from './set-configuration.command';
|
import { SetConfigurationCommand } from './set-configuration.command';
|
||||||
import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens';
|
import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens';
|
||||||
import {
|
import {
|
||||||
ConfigurationIdentifier,
|
Identifier,
|
||||||
ConfigurationType,
|
Type,
|
||||||
SetConfigurationRepositoryPort,
|
SetConfigurationRepositoryPort,
|
||||||
} from '@mobicoop/configuration-module';
|
} from '@mobicoop/configuration-module';
|
||||||
import { ConfigurationsManagerService } from '../../services/configurations-manager.service';
|
import { ConfigurationsManagerService } from '../../services/configurations-manager.service';
|
||||||
|
|
@ -18,21 +18,19 @@ export class SetConfigurationService implements ICommandHandler {
|
||||||
private readonly configurationsManager: ConfigurationsManagerService,
|
private readonly configurationsManager: ConfigurationsManagerService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async execute(
|
async execute(command: SetConfigurationCommand): Promise<Identifier> {
|
||||||
command: SetConfigurationCommand,
|
const type: Type = this.configurationsManager.identifierType(
|
||||||
): Promise<ConfigurationIdentifier> {
|
command.identifier,
|
||||||
const configurationType: ConfigurationType =
|
);
|
||||||
this.configurationsManager.identifierType(
|
|
||||||
command.configurationIdentifier,
|
|
||||||
);
|
|
||||||
const value: any = this.configurationsManager.cast(
|
const value: any = this.configurationsManager.cast(
|
||||||
`${command.value}`,
|
`${command.value}`,
|
||||||
configurationType,
|
type,
|
||||||
);
|
);
|
||||||
if (isNaN(value)) throw new ArgumentInvalidException('Bad value');
|
if ((type === Type.INT || type === Type.FLOAT) && isNaN(value))
|
||||||
|
throw new ArgumentInvalidException('Bad value');
|
||||||
return await this.configurationRepository.set(
|
return await this.configurationRepository.set(
|
||||||
command.configurationIdentifier.domain,
|
command.identifier.domain,
|
||||||
command.configurationIdentifier.key,
|
command.identifier.key,
|
||||||
value,
|
value,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { GetConfigurationQuery } from './get-configuration.query';
|
||||||
import { Inject } from '@nestjs/common';
|
import { Inject } from '@nestjs/common';
|
||||||
import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens';
|
import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens';
|
||||||
import {
|
import {
|
||||||
ConfigurationValue,
|
Value,
|
||||||
GetConfigurationRepositoryPort,
|
GetConfigurationRepositoryPort,
|
||||||
} from '@mobicoop/configuration-module';
|
} from '@mobicoop/configuration-module';
|
||||||
import { ConfigurationsManagerService } from '../../services/configurations-manager.service';
|
import { ConfigurationsManagerService } from '../../services/configurations-manager.service';
|
||||||
|
|
@ -15,11 +15,10 @@ export class GetConfigurationQueryHandler implements IQueryHandler {
|
||||||
private readonly configurationRepository: GetConfigurationRepositoryPort,
|
private readonly configurationRepository: GetConfigurationRepositoryPort,
|
||||||
private readonly configurationsManager: ConfigurationsManagerService,
|
private readonly configurationsManager: ConfigurationsManagerService,
|
||||||
) {}
|
) {}
|
||||||
async execute(query: GetConfigurationQuery): Promise<ConfigurationValue> {
|
async execute(query: GetConfigurationQuery): Promise<Value> {
|
||||||
return await this.configurationRepository.get(
|
return await this.configurationRepository.get(query.identifier.domain, {
|
||||||
query.configurationIdentifier.domain,
|
key: query.identifier.key,
|
||||||
query.configurationIdentifier.key,
|
type: this.configurationsManager.identifierType(query.identifier),
|
||||||
this.configurationsManager.identifierType(query.configurationIdentifier),
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,12 @@
|
||||||
import {
|
import { Domain, Identifier } from '@mobicoop/configuration-module';
|
||||||
ConfigurationDomain,
|
|
||||||
ConfigurationIdentifier,
|
|
||||||
} from '@mobicoop/configuration-module';
|
|
||||||
import { QueryBase } from '@mobicoop/ddd-library';
|
import { QueryBase } from '@mobicoop/ddd-library';
|
||||||
|
|
||||||
export class GetConfigurationQuery extends QueryBase {
|
export class GetConfigurationQuery extends QueryBase {
|
||||||
readonly configurationIdentifier: ConfigurationIdentifier;
|
readonly identifier: Identifier;
|
||||||
|
|
||||||
constructor(domain: ConfigurationDomain, key: string) {
|
constructor(domain: Domain, key: string) {
|
||||||
super();
|
super();
|
||||||
this.configurationIdentifier = {
|
this.identifier = {
|
||||||
domain,
|
domain,
|
||||||
key,
|
key,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
import {
|
import {
|
||||||
ConfigurationDomain,
|
Domain,
|
||||||
ConfigurationIdentifier,
|
Identifier,
|
||||||
ConfigurationType,
|
Type,
|
||||||
ConfigurationValue,
|
Value,
|
||||||
} from '@mobicoop/configuration-module';
|
} from '@mobicoop/configuration-module';
|
||||||
import { NotFoundException } from '@mobicoop/ddd-library';
|
import { NotFoundException } from '@mobicoop/ddd-library';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
import { AuthConfig } from '@src/config/auth.config';
|
||||||
import { CarpoolConfig } from '@src/config/carpool.config';
|
import { CarpoolConfig } from '@src/config/carpool.config';
|
||||||
import { Config } from '@src/config/config';
|
import { Config } from '@src/config/config';
|
||||||
|
import { GeographyConfig } from '@src/config/geography.config';
|
||||||
import { MatchConfig } from '@src/config/match.config';
|
import { MatchConfig } from '@src/config/match.config';
|
||||||
import { PaginationConfig } from '@src/config/pagination.config';
|
import { PaginationConfig } from '@src/config/pagination.config';
|
||||||
|
|
||||||
|
|
@ -18,62 +20,90 @@ export class ConfigurationsManagerService {
|
||||||
|
|
||||||
list = (): Config[] => {
|
list = (): Config[] => {
|
||||||
return [
|
return [
|
||||||
|
{
|
||||||
|
...(this.configService.get<AuthConfig>('auth') as AuthConfig),
|
||||||
|
domain: Domain.AUTH,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
...(this.configService.get<CarpoolConfig>('carpool') as CarpoolConfig),
|
...(this.configService.get<CarpoolConfig>('carpool') as CarpoolConfig),
|
||||||
domain: ConfigurationDomain.CARPOOL,
|
domain: Domain.CARPOOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...(this.configService.get<GeographyConfig>(
|
||||||
|
'geography',
|
||||||
|
) as GeographyConfig),
|
||||||
|
domain: Domain.GEOGRAPHY,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...(this.configService.get<MatchConfig>('match') as MatchConfig),
|
...(this.configService.get<MatchConfig>('match') as MatchConfig),
|
||||||
domain: ConfigurationDomain.MATCH,
|
domain: Domain.MATCH,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...(this.configService.get<PaginationConfig>(
|
...(this.configService.get<PaginationConfig>(
|
||||||
'pagination',
|
'pagination',
|
||||||
) as PaginationConfig),
|
) as PaginationConfig),
|
||||||
domain: ConfigurationDomain.PAGINATION,
|
domain: Domain.PAGINATION,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
identifierType = (
|
identifierType = (identifier: Identifier): Type => {
|
||||||
configurationIdentifier: ConfigurationIdentifier,
|
|
||||||
): ConfigurationType => {
|
|
||||||
const configs: Config[] = this.list();
|
const configs: Config[] = this.list();
|
||||||
const configuration: Config | undefined = configs.find(
|
const configuration: Config | undefined = configs.find(
|
||||||
(config: Config) =>
|
(config: Config) =>
|
||||||
config.domain === configurationIdentifier.domain &&
|
config.domain === identifier.domain &&
|
||||||
this._hasProperty(configurationIdentifier.key, config),
|
this._hasProperty(identifier.key, config),
|
||||||
);
|
);
|
||||||
if (!configuration)
|
if (!configuration)
|
||||||
throw new NotFoundException('Configuration item not found');
|
throw new NotFoundException('Configuration item not found');
|
||||||
return this.configurationType(
|
return this.configurationType(
|
||||||
this._getValue(configurationIdentifier.key, configuration),
|
this._getValue(identifier.key, configuration),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
configurationType = (value: any): ConfigurationType => {
|
configurationType = (value: any): Type => {
|
||||||
|
if (Array.isArray(value)) return this._configurationTypeArray(value);
|
||||||
switch (typeof value) {
|
switch (typeof value) {
|
||||||
case 'number':
|
case 'number':
|
||||||
if (this._isInt(value)) return ConfigurationType.INT;
|
if (this._isInt(value)) return Type.INT;
|
||||||
return ConfigurationType.FLOAT;
|
return Type.FLOAT;
|
||||||
case 'boolean':
|
case 'boolean':
|
||||||
return ConfigurationType.BOOLEAN;
|
return Type.BOOLEAN;
|
||||||
|
case 'object':
|
||||||
|
return Type.JSON;
|
||||||
default:
|
default:
|
||||||
return ConfigurationType.STRING;
|
if (value.indexOf(',') === -1) return Type.STRING;
|
||||||
|
return this._configurationTypeArray(value.split(','));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
cast = (
|
_configurationTypeArray = (value: Array<string | number>): Type => {
|
||||||
value: string,
|
return value.every((item) => typeof item === 'number' && this._isInt(item))
|
||||||
configurationType: ConfigurationType,
|
? Type.INT_ARRAY
|
||||||
): ConfigurationValue => {
|
: value.every((item) => typeof item === 'number')
|
||||||
switch (configurationType) {
|
? Type.FLOAT_ARRAY
|
||||||
case ConfigurationType.BOOLEAN:
|
: value.every((item) => typeof item === 'object')
|
||||||
|
? Type.JSON_ARRAY
|
||||||
|
: Type.STRING_ARRAY;
|
||||||
|
};
|
||||||
|
|
||||||
|
cast = (value: string, type: Type): Value => {
|
||||||
|
switch (type) {
|
||||||
|
case Type.BOOLEAN:
|
||||||
return value === 'true';
|
return value === 'true';
|
||||||
case ConfigurationType.INT:
|
case Type.INT:
|
||||||
return parseInt(value);
|
return parseInt(value);
|
||||||
case ConfigurationType.FLOAT:
|
case Type.FLOAT:
|
||||||
return parseFloat(value);
|
return parseFloat(value);
|
||||||
|
case Type.JSON:
|
||||||
|
case Type.JSON_ARRAY:
|
||||||
|
return JSON.parse(value);
|
||||||
|
case Type.INT_ARRAY:
|
||||||
|
return value.split(',').map((item: string) => parseInt(item));
|
||||||
|
case Type.FLOAT_ARRAY:
|
||||||
|
return value.split(',').map((item: string) => parseFloat(item));
|
||||||
|
case Type.STRING_ARRAY:
|
||||||
|
return value.split(',');
|
||||||
default:
|
default:
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,17 +35,20 @@ export class PopulateService implements OnApplicationBootstrap {
|
||||||
for (key in configuration) {
|
for (key in configuration) {
|
||||||
try {
|
try {
|
||||||
if (key !== 'domain')
|
if (key !== 'domain')
|
||||||
await this.getConfigurationRepository.get(
|
await this.getConfigurationRepository.get(config.domain, {
|
||||||
config.domain,
|
|
||||||
key,
|
key,
|
||||||
this.configurationsManager.configurationType(configuration[key]),
|
type: this.configurationsManager.configurationType(
|
||||||
);
|
configuration[key],
|
||||||
|
),
|
||||||
|
});
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (error instanceof NotFoundException) {
|
if (error instanceof NotFoundException) {
|
||||||
this.setConfigurationRepository.set(
|
this.setConfigurationRepository.set(
|
||||||
config.domain,
|
config.domain,
|
||||||
key,
|
key,
|
||||||
`${configuration[key]}`,
|
typeof configuration[key] === 'object'
|
||||||
|
? JSON.stringify(configuration[key])
|
||||||
|
: `${configuration[key]}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { ConfigurationType } from '@mobicoop/configuration-module';
|
import { Type } from '@mobicoop/configuration-module';
|
||||||
|
|
||||||
export class ConfigurationResponseDto {
|
export class ConfigurationResponseDto {
|
||||||
domain: string;
|
domain: string;
|
||||||
key: string;
|
key: string;
|
||||||
value: string | boolean | number;
|
value: string | boolean | number | object | string[] | number[] | object[];
|
||||||
type: ConfigurationType;
|
type: Type;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { ConfigurationDomain } from '@mobicoop/configuration-module';
|
import { Domain } from '@mobicoop/configuration-module';
|
||||||
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
export class GetConfigurationRequestDto {
|
export class GetConfigurationRequestDto {
|
||||||
@IsEnum(ConfigurationDomain)
|
@IsEnum(Domain)
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
domain: ConfigurationDomain;
|
domain: Domain;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { ConfigurationDomain } from '@mobicoop/configuration-module';
|
import { Domain } from '@mobicoop/configuration-module';
|
||||||
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
export class SetConfigurationRequestDto {
|
export class SetConfigurationRequestDto {
|
||||||
@IsEnum(ConfigurationDomain)
|
@IsEnum(Domain)
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
domain: ConfigurationDomain;
|
domain: Domain;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import {
|
||||||
RpcExceptionCode,
|
RpcExceptionCode,
|
||||||
RpcValidationPipe,
|
RpcValidationPipe,
|
||||||
} from '@mobicoop/ddd-library';
|
} from '@mobicoop/ddd-library';
|
||||||
import { ConfigurationValue } from '@mobicoop/configuration-module';
|
import { Value } from '@mobicoop/configuration-module';
|
||||||
|
|
||||||
@UsePipes(
|
@UsePipes(
|
||||||
new RpcValidationPipe({
|
new RpcValidationPipe({
|
||||||
|
|
@ -31,11 +31,10 @@ export class GetConfigurationGrpcController {
|
||||||
data: GetConfigurationRequestDto,
|
data: GetConfigurationRequestDto,
|
||||||
): Promise<ConfigurationResponseDto> {
|
): Promise<ConfigurationResponseDto> {
|
||||||
try {
|
try {
|
||||||
const configurationValue: ConfigurationValue =
|
const value: Value = await this.queryBus.execute(
|
||||||
await this.queryBus.execute(
|
new GetConfigurationQuery(data.domain, data.key),
|
||||||
new GetConfigurationQuery(data.domain, data.key),
|
);
|
||||||
);
|
return this.mapper.toResponse(data, value);
|
||||||
return this.mapper.toResponse(data, configurationValue);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof NotFoundException) {
|
if (e instanceof NotFoundException) {
|
||||||
throw new RpcException({
|
throw new RpcException({
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { RpcExceptionCode, RpcValidationPipe } from '@mobicoop/ddd-library';
|
||||||
import { GRPC_SERVICE_NAME } from '@src/app.constants';
|
import { GRPC_SERVICE_NAME } from '@src/app.constants';
|
||||||
import { SetConfigurationRequestDto } from './dtos/set-configuration.request.dto';
|
import { SetConfigurationRequestDto } from './dtos/set-configuration.request.dto';
|
||||||
import { SetConfigurationCommand } from '@modules/configuration/core/application/commands/set-configuration/set-configuration.command';
|
import { SetConfigurationCommand } from '@modules/configuration/core/application/commands/set-configuration/set-configuration.command';
|
||||||
import { ConfigurationIdentifier } from '@mobicoop/configuration-module';
|
import { Identifier } from '@mobicoop/configuration-module';
|
||||||
|
|
||||||
@UsePipes(
|
@UsePipes(
|
||||||
new RpcValidationPipe({
|
new RpcValidationPipe({
|
||||||
|
|
@ -20,19 +20,18 @@ export class SetConfigurationGrpcController {
|
||||||
@GrpcMethod(GRPC_SERVICE_NAME, 'Set')
|
@GrpcMethod(GRPC_SERVICE_NAME, 'Set')
|
||||||
async set(
|
async set(
|
||||||
setConfigurationRequestDto: SetConfigurationRequestDto,
|
setConfigurationRequestDto: SetConfigurationRequestDto,
|
||||||
): Promise<ConfigurationIdentifier> {
|
): Promise<Identifier> {
|
||||||
try {
|
try {
|
||||||
const configurationIdentifier: ConfigurationIdentifier =
|
const identifier: Identifier = await this.commandBus.execute(
|
||||||
await this.commandBus.execute(
|
new SetConfigurationCommand({
|
||||||
new SetConfigurationCommand({
|
identifier: {
|
||||||
configurationIdentifier: {
|
domain: setConfigurationRequestDto.domain,
|
||||||
domain: setConfigurationRequestDto.domain,
|
key: setConfigurationRequestDto.key,
|
||||||
key: setConfigurationRequestDto.key,
|
},
|
||||||
},
|
value: setConfigurationRequestDto.value,
|
||||||
value: setConfigurationRequestDto.value,
|
}),
|
||||||
}),
|
);
|
||||||
);
|
return identifier;
|
||||||
return configurationIdentifier;
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
throw new RpcException({
|
throw new RpcException({
|
||||||
code: RpcExceptionCode.UNKNOWN,
|
code: RpcExceptionCode.UNKNOWN,
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
import {
|
import { Domain, Type } from '@mobicoop/configuration-module';
|
||||||
ConfigurationDomain,
|
|
||||||
ConfigurationType,
|
|
||||||
} from '@mobicoop/configuration-module';
|
|
||||||
import { ConfigurationMapper } from '@modules/configuration/configuration.mapper';
|
import { ConfigurationMapper } from '@modules/configuration/configuration.mapper';
|
||||||
import { ConfigurationsManagerService } from '@modules/configuration/core/application/services/configurations-manager.service';
|
import { ConfigurationsManagerService } from '@modules/configuration/core/application/services/configurations-manager.service';
|
||||||
import { ConfigurationResponseDto } from '@modules/configuration/interface/dtos/configuration.response.dto';
|
import { ConfigurationResponseDto } from '@modules/configuration/interface/dtos/configuration.response.dto';
|
||||||
import { Test } from '@nestjs/testing';
|
import { Test } from '@nestjs/testing';
|
||||||
|
|
||||||
const mockConfigurationsManagerService = {
|
const mockConfigurationsManagerService = {
|
||||||
configurationType: jest.fn().mockImplementation(() => ConfigurationType.INT),
|
configurationType: jest.fn().mockImplementation(() => Type.INT),
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Configuration Mapper', () => {
|
describe('Configuration Mapper', () => {
|
||||||
|
|
@ -34,7 +31,7 @@ describe('Configuration Mapper', () => {
|
||||||
it('should map configuration to response', async () => {
|
it('should map configuration to response', async () => {
|
||||||
const mapped: ConfigurationResponseDto = configurationMapper.toResponse(
|
const mapped: ConfigurationResponseDto = configurationMapper.toResponse(
|
||||||
{
|
{
|
||||||
domain: ConfigurationDomain.CARPOOL,
|
domain: Domain.CARPOOL,
|
||||||
key: 'seatsProposed',
|
key: 'seatsProposed',
|
||||||
},
|
},
|
||||||
'3',
|
'3',
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,4 @@
|
||||||
import {
|
import { Domain, Identifier, Type } from '@mobicoop/configuration-module';
|
||||||
ConfigurationDomain,
|
|
||||||
ConfigurationIdentifier,
|
|
||||||
ConfigurationType,
|
|
||||||
} from '@mobicoop/configuration-module';
|
|
||||||
import { NotFoundException } from '@mobicoop/ddd-library';
|
import { NotFoundException } from '@mobicoop/ddd-library';
|
||||||
import { ConfigurationsManagerService } from '@modules/configuration/core/application/services/configurations-manager.service';
|
import { ConfigurationsManagerService } from '@modules/configuration/core/application/services/configurations-manager.service';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
|
@ -12,6 +8,10 @@ import { Config } from '@src/config/config';
|
||||||
const mockConfigService = {
|
const mockConfigService = {
|
||||||
get: jest.fn().mockImplementation((domain: string) => {
|
get: jest.fn().mockImplementation((domain: string) => {
|
||||||
switch (domain) {
|
switch (domain) {
|
||||||
|
case 'auth':
|
||||||
|
return {
|
||||||
|
encryptionAlgorithm: 'BCRYPT',
|
||||||
|
};
|
||||||
case 'carpool':
|
case 'carpool':
|
||||||
return {
|
return {
|
||||||
departureTimeMargin: 900,
|
departureTimeMargin: 900,
|
||||||
|
|
@ -20,6 +20,21 @@ const mockConfigService = {
|
||||||
seatsRequested: 1,
|
seatsRequested: 1,
|
||||||
strictFrequency: false,
|
strictFrequency: false,
|
||||||
};
|
};
|
||||||
|
case 'geography':
|
||||||
|
return {
|
||||||
|
georouterType: 'graphhopper',
|
||||||
|
georouterUrl: 'http://localhost:8989',
|
||||||
|
geocoderLang: 'fr',
|
||||||
|
geocoderMinConfidence: 0.3,
|
||||||
|
geocoderMaxResultsPerProvider: 5,
|
||||||
|
geocoderMaxResultsPerType: 5,
|
||||||
|
geocoderSanitize: true,
|
||||||
|
geocoderConsolidate: true,
|
||||||
|
geocoderProximity: 5,
|
||||||
|
geocoderPopulationPrioritizerCoef: 100,
|
||||||
|
geocoderProviders: [{ name: 'provider1' }, { name: 'provider2' }],
|
||||||
|
geocoderProvidersFallback: [{ name: 'provider3' }],
|
||||||
|
};
|
||||||
case 'match':
|
case 'match':
|
||||||
return {
|
return {
|
||||||
algorithm: 'PASSENGER_ORIENTED',
|
algorithm: 'PASSENGER_ORIENTED',
|
||||||
|
|
@ -64,73 +79,126 @@ describe('Configurations Manager Service', () => {
|
||||||
|
|
||||||
it('should return the list of configuration elements', () => {
|
it('should return the list of configuration elements', () => {
|
||||||
const list: Config[] = configurationsManagerService.list();
|
const list: Config[] = configurationsManagerService.list();
|
||||||
expect(list).toHaveLength(3);
|
expect(list).toHaveLength(5);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('identifierType', () => {
|
describe('identifierType', () => {
|
||||||
it('should return the type of a configuration item for a given identifier', () => {
|
it('should return the type of a configuration item for a given identifier', () => {
|
||||||
const configurationIdentifier: ConfigurationIdentifier = {
|
const identifier: Identifier = {
|
||||||
domain: ConfigurationDomain.CARPOOL,
|
domain: Domain.CARPOOL,
|
||||||
key: 'seatsProposed',
|
key: 'seatsProposed',
|
||||||
};
|
};
|
||||||
const configurationType: ConfigurationType =
|
const type: Type =
|
||||||
configurationsManagerService.identifierType(configurationIdentifier);
|
configurationsManagerService.identifierType(identifier);
|
||||||
expect(configurationType).toBe(ConfigurationType.INT);
|
expect(type).toBe(Type.INT);
|
||||||
});
|
});
|
||||||
it('should throw if configuration item is not found', () => {
|
it('should throw if configuration item is not found', () => {
|
||||||
const configurationIdentifier: ConfigurationIdentifier = {
|
const identifier: Identifier = {
|
||||||
domain: ConfigurationDomain.MATCH,
|
domain: Domain.MATCH,
|
||||||
key: 'maxDetour',
|
key: 'maxDetour',
|
||||||
};
|
};
|
||||||
expect(() => {
|
expect(() => {
|
||||||
configurationsManagerService.identifierType(configurationIdentifier);
|
configurationsManagerService.identifierType(identifier);
|
||||||
}).toThrow(NotFoundException);
|
}).toThrow(NotFoundException);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('configurationType', () => {
|
describe('Type', () => {
|
||||||
it('should return the configuration type of an int', () => {
|
it('should return the configuration type of an int', () => {
|
||||||
expect(configurationsManagerService.configurationType(3)).toBe(
|
expect(configurationsManagerService.configurationType(3)).toBe(Type.INT);
|
||||||
ConfigurationType.INT,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
it('should return the configuration type of a float', () => {
|
it('should return the configuration type of a float', () => {
|
||||||
expect(configurationsManagerService.configurationType(3.5)).toBe(
|
expect(configurationsManagerService.configurationType(3.5)).toBe(
|
||||||
ConfigurationType.FLOAT,
|
Type.FLOAT,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('should return the configuration type of a boolean', () => {
|
it('should return the configuration type of a boolean', () => {
|
||||||
expect(configurationsManagerService.configurationType(true)).toBe(
|
expect(configurationsManagerService.configurationType(true)).toBe(
|
||||||
ConfigurationType.BOOLEAN,
|
Type.BOOLEAN,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('should return the configuration type of a string', () => {
|
it('should return the configuration type of a string', () => {
|
||||||
expect(configurationsManagerService.configurationType('role')).toBe(
|
expect(configurationsManagerService.configurationType('role')).toBe(
|
||||||
ConfigurationType.STRING,
|
Type.STRING,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
it('should return the configuration type of a json object', () => {
|
||||||
|
expect(
|
||||||
|
configurationsManagerService.configurationType({ key: 'value' }),
|
||||||
|
).toBe(Type.JSON);
|
||||||
|
});
|
||||||
|
it('should return the configuration type of a string array', () => {
|
||||||
|
expect(
|
||||||
|
configurationsManagerService.configurationType(['test', 'test2']),
|
||||||
|
).toBe(Type.STRING_ARRAY);
|
||||||
|
expect(configurationsManagerService.configurationType('test,test2')).toBe(
|
||||||
|
Type.STRING_ARRAY,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('should return the configuration type of an int array', () => {
|
||||||
|
expect(configurationsManagerService.configurationType([2, 3])).toBe(
|
||||||
|
Type.INT_ARRAY,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('should return the configuration type of a float array', () => {
|
||||||
|
expect(configurationsManagerService.configurationType([1.2, 3.6])).toBe(
|
||||||
|
Type.FLOAT_ARRAY,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('should return the configuration type of a json array', () => {
|
||||||
|
expect(
|
||||||
|
configurationsManagerService.configurationType([
|
||||||
|
{ key1: 'value1' },
|
||||||
|
{ key2: 'value2' },
|
||||||
|
]),
|
||||||
|
).toBe(Type.JSON_ARRAY);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('cast', () => {
|
describe('cast', () => {
|
||||||
it('should cast a string to int', () => {
|
it('should cast a string to int', () => {
|
||||||
expect(
|
expect(configurationsManagerService.cast('1', Type.INT)).toBe(1);
|
||||||
configurationsManagerService.cast('1', ConfigurationType.INT),
|
|
||||||
).toBe(1);
|
|
||||||
});
|
});
|
||||||
it('should cast a string to float', () => {
|
it('should cast a string to float', () => {
|
||||||
expect(
|
expect(configurationsManagerService.cast('1.5', Type.FLOAT)).toBe(1.5);
|
||||||
configurationsManagerService.cast('1.5', ConfigurationType.FLOAT),
|
|
||||||
).toBe(1.5);
|
|
||||||
});
|
});
|
||||||
it('should cast a string to boolean', () => {
|
it('should cast a string to boolean', () => {
|
||||||
expect(
|
expect(
|
||||||
configurationsManagerService.cast('true', ConfigurationType.BOOLEAN),
|
configurationsManagerService.cast('true', Type.BOOLEAN),
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
it('should not cast a string and return it as is', () => {
|
it('should not cast a string and return it as is', () => {
|
||||||
|
expect(configurationsManagerService.cast('role', Type.STRING)).toBe(
|
||||||
|
'role',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('should cast a string to json object', () => {
|
||||||
expect(
|
expect(
|
||||||
configurationsManagerService.cast('role', ConfigurationType.STRING),
|
configurationsManagerService.cast('{"key":"value"}', Type.JSON),
|
||||||
).toBe('role');
|
).toStrictEqual({ key: 'value' });
|
||||||
|
});
|
||||||
|
it('should cast a string to an array of strings', () => {
|
||||||
|
expect(
|
||||||
|
configurationsManagerService.cast('test,test2', Type.STRING_ARRAY),
|
||||||
|
).toStrictEqual(['test', 'test2']);
|
||||||
|
});
|
||||||
|
it('should cast a string to an array of ints', () => {
|
||||||
|
expect(
|
||||||
|
configurationsManagerService.cast('1,2', Type.INT_ARRAY),
|
||||||
|
).toStrictEqual([1, 2]);
|
||||||
|
});
|
||||||
|
it('should cast a string to an array of floats', () => {
|
||||||
|
expect(
|
||||||
|
configurationsManagerService.cast('1.2,2.3', Type.FLOAT_ARRAY),
|
||||||
|
).toStrictEqual([1.2, 2.3]);
|
||||||
|
});
|
||||||
|
it('should cast a string to an array of json objects', () => {
|
||||||
|
expect(
|
||||||
|
configurationsManagerService.cast(
|
||||||
|
'[{"key1":"value1"},{"key2":"value2"}]',
|
||||||
|
Type.JSON_ARRAY,
|
||||||
|
),
|
||||||
|
).toStrictEqual([{ key1: 'value1' }, { key2: 'value2' }]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,21 +2,17 @@ import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { GetConfigurationQueryHandler } from '@modules/configuration/core/application/queries/get-configuration/get-configuration.query-handler';
|
import { GetConfigurationQueryHandler } from '@modules/configuration/core/application/queries/get-configuration/get-configuration.query-handler';
|
||||||
import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens';
|
import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens';
|
||||||
import { GetConfigurationQuery } from '@modules/configuration/core/application/queries/get-configuration/get-configuration.query';
|
import { GetConfigurationQuery } from '@modules/configuration/core/application/queries/get-configuration/get-configuration.query';
|
||||||
import {
|
import { Domain, Type, Value } from '@mobicoop/configuration-module';
|
||||||
ConfigurationDomain,
|
|
||||||
ConfigurationType,
|
|
||||||
ConfigurationValue,
|
|
||||||
} from '@mobicoop/configuration-module';
|
|
||||||
import { ConfigurationsManagerService } from '@modules/configuration/core/application/services/configurations-manager.service';
|
import { ConfigurationsManagerService } from '@modules/configuration/core/application/services/configurations-manager.service';
|
||||||
|
|
||||||
const configurationValue: ConfigurationValue = '3';
|
const value: Value = '3';
|
||||||
|
|
||||||
const mockConfigurationRepository = {
|
const mockConfigurationRepository = {
|
||||||
get: jest.fn().mockImplementation(() => configurationValue),
|
get: jest.fn().mockImplementation(() => value),
|
||||||
};
|
};
|
||||||
|
|
||||||
const mockConfigurationsManagerService = {
|
const mockConfigurationsManagerService = {
|
||||||
identifierType: jest.fn().mockImplementation(() => ConfigurationType.INT),
|
identifierType: jest.fn().mockImplementation(() => Type.INT),
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Get Configuration Query Handler', () => {
|
describe('Get Configuration Query Handler', () => {
|
||||||
|
|
@ -49,12 +45,13 @@ describe('Get Configuration Query Handler', () => {
|
||||||
describe('execution', () => {
|
describe('execution', () => {
|
||||||
it('should return a configuration value', async () => {
|
it('should return a configuration value', async () => {
|
||||||
const getConfigurationQuery = new GetConfigurationQuery(
|
const getConfigurationQuery = new GetConfigurationQuery(
|
||||||
ConfigurationDomain.CARPOOL,
|
Domain.CARPOOL,
|
||||||
'seatsProposed',
|
'seatsProposed',
|
||||||
);
|
);
|
||||||
const configurationValue: ConfigurationValue =
|
const value: Value = await getConfigurationQueryHandler.execute(
|
||||||
await getConfigurationQueryHandler.execute(getConfigurationQuery);
|
getConfigurationQuery,
|
||||||
expect(configurationValue).toBe('3');
|
);
|
||||||
|
expect(value).toBe('3');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
import {
|
import { Domain, NotFoundException } from '@mobicoop/configuration-module';
|
||||||
ConfigurationDomain,
|
|
||||||
NotFoundException,
|
|
||||||
} from '@mobicoop/configuration-module';
|
|
||||||
import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens';
|
import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens';
|
||||||
import { ConfigurationsManagerService } from '@modules/configuration/core/application/services/configurations-manager.service';
|
import { ConfigurationsManagerService } from '@modules/configuration/core/application/services/configurations-manager.service';
|
||||||
import { PopulateService } from '@modules/configuration/core/application/services/populate.service';
|
import { PopulateService } from '@modules/configuration/core/application/services/populate.service';
|
||||||
|
|
@ -20,7 +17,7 @@ const mockConfigurationRepository = {
|
||||||
const mockConfigurationsManagerService = {
|
const mockConfigurationsManagerService = {
|
||||||
list: jest.fn().mockImplementation(() => [
|
list: jest.fn().mockImplementation(() => [
|
||||||
{
|
{
|
||||||
domain: ConfigurationDomain.CARPOOL,
|
domain: Domain.CARPOOL,
|
||||||
departureTimeMargin: 900,
|
departureTimeMargin: 900,
|
||||||
role: 'passenger',
|
role: 'passenger',
|
||||||
seatsProposed: 3,
|
seatsProposed: 3,
|
||||||
|
|
@ -28,7 +25,7 @@ const mockConfigurationsManagerService = {
|
||||||
strictFrequency: false,
|
strictFrequency: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
domain: ConfigurationDomain.PAGINATION,
|
domain: Domain.PAGINATION,
|
||||||
perPage: 10,
|
perPage: 10,
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,11 @@ import { SetConfigurationRequestDto } from '@modules/configuration/interface/grp
|
||||||
import { SetConfigurationService } from '@modules/configuration/core/application/commands/set-configuration/set-configuration.service';
|
import { SetConfigurationService } from '@modules/configuration/core/application/commands/set-configuration/set-configuration.service';
|
||||||
import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens';
|
import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens';
|
||||||
import { SetConfigurationCommand } from '@modules/configuration/core/application/commands/set-configuration/set-configuration.command';
|
import { SetConfigurationCommand } from '@modules/configuration/core/application/commands/set-configuration/set-configuration.command';
|
||||||
import {
|
import { Domain, Type } from '@mobicoop/configuration-module';
|
||||||
ConfigurationDomain,
|
|
||||||
ConfigurationType,
|
|
||||||
} from '@mobicoop/configuration-module';
|
|
||||||
import { ConfigurationsManagerService } from '@modules/configuration/core/application/services/configurations-manager.service';
|
import { ConfigurationsManagerService } from '@modules/configuration/core/application/services/configurations-manager.service';
|
||||||
|
|
||||||
const setConfigurationRequest: SetConfigurationRequestDto = {
|
const setConfigurationRequest: SetConfigurationRequestDto = {
|
||||||
domain: ConfigurationDomain.CARPOOL,
|
domain: Domain.CARPOOL,
|
||||||
key: 'seatsProposed',
|
key: 'seatsProposed',
|
||||||
value: '3',
|
value: '3',
|
||||||
};
|
};
|
||||||
|
|
@ -25,7 +22,7 @@ const mockConfigurationRepository = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const mockConfigurationsManagerService = {
|
const mockConfigurationsManagerService = {
|
||||||
identifierType: jest.fn().mockImplementation(() => ConfigurationType.INT),
|
identifierType: jest.fn().mockImplementation(() => Type.INT),
|
||||||
cast: jest.fn().mockImplementation(() => 3),
|
cast: jest.fn().mockImplementation(() => 3),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -58,7 +55,7 @@ describe('Set Configuration Service', () => {
|
||||||
|
|
||||||
describe('execution', () => {
|
describe('execution', () => {
|
||||||
const setConfigurationCommand = new SetConfigurationCommand({
|
const setConfigurationCommand = new SetConfigurationCommand({
|
||||||
configurationIdentifier: {
|
identifier: {
|
||||||
domain: setConfigurationRequest.domain,
|
domain: setConfigurationRequest.domain,
|
||||||
key: setConfigurationRequest.key,
|
key: setConfigurationRequest.key,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { ConfigurationDomain } from '@mobicoop/configuration-module';
|
import { Domain } from '@mobicoop/configuration-module';
|
||||||
import { NotFoundException, RpcExceptionCode } from '@mobicoop/ddd-library';
|
import { NotFoundException, RpcExceptionCode } from '@mobicoop/ddd-library';
|
||||||
import { ConfigurationMapper } from '@modules/configuration/configuration.mapper';
|
import { ConfigurationMapper } from '@modules/configuration/configuration.mapper';
|
||||||
import { GetConfigurationGrpcController } from '@modules/configuration/interface/grpc-controllers/get-configuration.grpc.controller';
|
import { GetConfigurationGrpcController } from '@modules/configuration/interface/grpc-controllers/get-configuration.grpc.controller';
|
||||||
|
|
@ -20,7 +20,7 @@ const mockQueryBus = {
|
||||||
|
|
||||||
const mockConfigurationMapper = {
|
const mockConfigurationMapper = {
|
||||||
toResponse: jest.fn().mockImplementationOnce(() => ({
|
toResponse: jest.fn().mockImplementationOnce(() => ({
|
||||||
domain: ConfigurationDomain.CARPOOL,
|
domain: Domain.CARPOOL,
|
||||||
key: 'seatsProposed',
|
key: 'seatsProposed',
|
||||||
value: '3',
|
value: '3',
|
||||||
})),
|
})),
|
||||||
|
|
@ -61,7 +61,7 @@ describe('Get Configuration Grpc Controller', () => {
|
||||||
jest.spyOn(mockQueryBus, 'execute');
|
jest.spyOn(mockQueryBus, 'execute');
|
||||||
jest.spyOn(mockConfigurationMapper, 'toResponse');
|
jest.spyOn(mockConfigurationMapper, 'toResponse');
|
||||||
const response = await getConfigurationGrpcController.get({
|
const response = await getConfigurationGrpcController.get({
|
||||||
domain: ConfigurationDomain.CARPOOL,
|
domain: Domain.CARPOOL,
|
||||||
key: 'seatsProposed',
|
key: 'seatsProposed',
|
||||||
});
|
});
|
||||||
expect(response.value).toBe('3');
|
expect(response.value).toBe('3');
|
||||||
|
|
@ -75,7 +75,7 @@ describe('Get Configuration Grpc Controller', () => {
|
||||||
expect.assertions(4);
|
expect.assertions(4);
|
||||||
try {
|
try {
|
||||||
await getConfigurationGrpcController.get({
|
await getConfigurationGrpcController.get({
|
||||||
domain: ConfigurationDomain.CARPOOL,
|
domain: Domain.CARPOOL,
|
||||||
key: 'price',
|
key: 'price',
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
|
@ -92,7 +92,7 @@ describe('Get Configuration Grpc Controller', () => {
|
||||||
expect.assertions(4);
|
expect.assertions(4);
|
||||||
try {
|
try {
|
||||||
await getConfigurationGrpcController.get({
|
await getConfigurationGrpcController.get({
|
||||||
domain: ConfigurationDomain.CARPOOL,
|
domain: Domain.CARPOOL,
|
||||||
key: 'someValue',
|
key: 'someValue',
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
import {
|
import { Domain, Identifier } from '@mobicoop/configuration-module';
|
||||||
ConfigurationDomain,
|
|
||||||
ConfigurationIdentifier,
|
|
||||||
} from '@mobicoop/configuration-module';
|
|
||||||
import { RpcExceptionCode } from '@mobicoop/ddd-library';
|
import { RpcExceptionCode } from '@mobicoop/ddd-library';
|
||||||
import { SetConfigurationRequestDto } from '@modules/configuration/interface/grpc-controllers/dtos/set-configuration.request.dto';
|
import { SetConfigurationRequestDto } from '@modules/configuration/interface/grpc-controllers/dtos/set-configuration.request.dto';
|
||||||
import { SetConfigurationGrpcController } from '@modules/configuration/interface/grpc-controllers/set-configuration.grpc.controller';
|
import { SetConfigurationGrpcController } from '@modules/configuration/interface/grpc-controllers/set-configuration.grpc.controller';
|
||||||
|
|
@ -10,7 +7,7 @@ import { RpcException } from '@nestjs/microservices';
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
|
||||||
const setConfigurationRequest: SetConfigurationRequestDto = {
|
const setConfigurationRequest: SetConfigurationRequestDto = {
|
||||||
domain: ConfigurationDomain.CARPOOL,
|
domain: Domain.CARPOOL,
|
||||||
key: 'seatsProposed',
|
key: 'seatsProposed',
|
||||||
value: '3',
|
value: '3',
|
||||||
};
|
};
|
||||||
|
|
@ -19,7 +16,7 @@ const mockCommandBus = {
|
||||||
execute: jest
|
execute: jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockImplementationOnce(() => ({
|
.mockImplementationOnce(() => ({
|
||||||
domain: ConfigurationDomain.CARPOOL,
|
domain: Domain.CARPOOL,
|
||||||
key: 'seatsProposed',
|
key: 'seatsProposed',
|
||||||
}))
|
}))
|
||||||
.mockImplementationOnce(() => {
|
.mockImplementationOnce(() => {
|
||||||
|
|
@ -56,9 +53,10 @@ describe('Set Configuration Grpc Controller', () => {
|
||||||
|
|
||||||
it('should set a configuration item', async () => {
|
it('should set a configuration item', async () => {
|
||||||
jest.spyOn(mockCommandBus, 'execute');
|
jest.spyOn(mockCommandBus, 'execute');
|
||||||
const configurationIdentifier: ConfigurationIdentifier =
|
const identifier: Identifier = await setConfigurationGrpcController.set(
|
||||||
await setConfigurationGrpcController.set(setConfigurationRequest);
|
setConfigurationRequest,
|
||||||
expect(configurationIdentifier.key).toBe('seatsProposed');
|
);
|
||||||
|
expect(identifier.key).toBe('seatsProposed');
|
||||||
expect(mockCommandBus.execute).toHaveBeenCalledTimes(1);
|
expect(mockCommandBus.execute).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
"paths": {
|
"paths": {
|
||||||
"@libs/*": ["src/libs/*"],
|
"@libs/*": ["src/libs/*"],
|
||||||
"@modules/*": ["src/modules/*"],
|
"@modules/*": ["src/modules/*"],
|
||||||
"@src/*": ["src/*"]
|
"@src/*": ["src/*"],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue