From 5094e27ad1442aa96fdd66d8f1c432a59ecafc1e Mon Sep 17 00:00:00 2001 From: sbriat Date: Wed, 25 Oct 2023 16:03:17 +0200 Subject: [PATCH 1/2] use configuration package as middleware --- README.md | 8 +- package-lock.json | 747 ++++++++++-------- package.json | 8 +- src/app.module.ts | 17 +- src/config/carpool.config.ts | 8 + src/config/pagination.config.ts | 4 + .../configuration/configuration.mapper.ts | 59 +- .../configuration/configuration.module.ts | 2 +- .../set-configuration.service.ts | 15 +- .../ports/configuration.repository.port.ts | 13 - .../get-configuration.query-handler.ts | 12 +- .../application/services/populate.service.ts | 24 +- .../core/domain/configuration.entity.ts | 21 - .../core/domain/configuration.types.ts | 36 - .../configuration.repository.ts | 47 -- .../dtos/configuration.response.dto.ts | 4 +- .../dtos/get-configuration.request.dto.ts | 2 +- .../dtos/set-configuration.request.dto.ts | 2 +- .../get-configuration.grpc.controller.ts | 19 +- .../set-configuration.grpc.controller.ts | 14 +- .../tests/unit/configuration.mapper.spec.ts | 51 +- .../unit/core/configuration.entity.spec.ts | 23 - .../get-configuration.query-handler.spec.ts | 28 +- .../tests/unit/core/populate.service.spec.ts | 20 +- .../core/set-configuration.service.spec.ts | 9 +- .../configuration.repository.spec.ts | 93 --- .../get-configuration.grpc.controller.spec.ts | 5 +- .../set-configuration.grpc.controller.spec.ts | 14 +- 28 files changed, 558 insertions(+), 747 deletions(-) delete mode 100644 src/modules/configuration/core/application/ports/configuration.repository.port.ts delete mode 100644 src/modules/configuration/core/domain/configuration.entity.ts delete mode 100644 src/modules/configuration/core/domain/configuration.types.ts delete mode 100644 src/modules/configuration/infrastructure/configuration.repository.ts delete mode 100644 src/modules/configuration/tests/unit/core/configuration.entity.spec.ts delete mode 100644 src/modules/configuration/tests/unit/infrastructure/configuration.repository.spec.ts diff --git a/README.md b/README.md index e36c81e..c757533 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Mobicoop V3 - Configuration Service -Configuration items management. Used to configure and store all services using redis as database. +Configuration items management. Used to configure and store configuration items for all Mobicoop V3 services using redis as database. Each item consists in : @@ -8,10 +8,6 @@ Each item consists in : - a **key** : the key of the configuration item (a string) - a **value** : the value of the configuration item (always a string, each service must cast the value if needed) -This service centralizes the configuration items, but theoratically each service should "push" its items toward the configuration service. - -Practically, it's the other way round as it's easier to use this configuration service as the single source of truth. This is why configuration items key and domain are immutable : services may use hardcoded domain-key pairs. Therefore, only values can be updated. - ## Available domains - **CARPOOL** : carpool related configuration items (eg. default number of seats proposed as a driver) @@ -27,8 +23,6 @@ You also need NodeJS installed locally : we **strongly** advise to install [Node The API will run inside a docker container, **but** the install itself is made outside the container, because during development we need tools that need to be available locally (eg. ESLint, Prettier...). -A RabbitMQ instance is also required to send / receive messages when data has been inserted/updated/deleted. - ## Installation - copy `.env.dist` to `.env` : diff --git a/package-lock.json b/package-lock.json index 3e22f04..bd173ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@grpc/grpc-js": "^1.9.6", "@grpc/proto-loader": "^0.7.10", + "@mobicoop/configuration-module": "^4.0.0", "@mobicoop/ddd-library": "^2.1.1", "@mobicoop/health-module": "^2.3.1", "@mobicoop/message-broker-module": "^2.1.1", @@ -22,15 +23,10 @@ "@nestjs/microservices": "^10.2.7", "@nestjs/platform-express": "^10.2.7", "@nestjs/terminus": "^10.1.1", - "@prisma/client": "^5.4.2", - "@songkeys/nestjs-redis": "^10.0.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", - "ioredis": "^5.3.2", "reflect-metadata": "^0.1.13", - "rimraf": "^5.0.5", - "rxjs": "^7.8.1", - "uuid": "^9.0.1" + "rimraf": "^5.0.5" }, "devDependencies": { "@nestjs/cli": "^10.1.18", @@ -40,7 +36,6 @@ "@types/jest": "29.5.6", "@types/node": "^20.8.7", "@types/supertest": "^2.0.15", - "@types/uuid": "^9.0.6", "@typescript-eslint/eslint-plugin": "^6.8.0", "@typescript-eslint/parser": "^6.8.0", "dotenv-cli": "^7.3.0", @@ -49,7 +44,6 @@ "eslint-plugin-prettier": "^5.0.1", "jest": "29.7.0", "prettier": "^3.0.3", - "prisma": "^5.4.2", "source-map-support": "^0.5.21", "supertest": "^6.3.3", "ts-jest": "29.1.1", @@ -95,9 +89,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "16.2.3", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.3.tgz", - "integrity": "sha512-oZLdg2XTx7likYAXRj1CU0XmrsCfe5f2grj3iwuI3OB1LXwwpdbHBztruj03y3yHES+TnO+dIbkvRnvMXs7uAA==", + "version": "16.2.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.7.tgz", + "integrity": "sha512-XskObYrg7NRdEuHnSVZOM7OeinEL8HzugjmKnawAa+dAbFCCoGsVWjMliA/Q8sb1yfGkyL0WW7DZABZj7EGwWA==", "dev": true, "dependencies": { "ajv": "8.12.0", @@ -122,12 +116,12 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "16.2.3", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.3.tgz", - "integrity": "sha512-+lBiHxi/C9HCfiCbtW25DldwvJDXXXv5oWw+Tg4s18BO/lYZLveGUEaZWu9ZJ5VIJ8GliUi2LohxhDxBkh4Oxg==", + "version": "16.2.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.7.tgz", + "integrity": "sha512-zu3xHwA4w+kXHkyyjGl3i7uSU2/kKLPKuyyixw0WLcKUQCYd7TWmu8OC0qCDa42XkxP9gGL091dJFu56exgneA==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.3", + "@angular-devkit/core": "16.2.7", "jsonc-parser": "3.2.0", "magic-string": "0.30.1", "ora": "5.4.1", @@ -140,13 +134,13 @@ } }, "node_modules/@angular-devkit/schematics-cli": { - "version": "16.2.3", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-16.2.3.tgz", - "integrity": "sha512-5YQCbQmY9Kc03a9Io4XHOrxGXjnzcVveUuUO64R1m5x2aA5I+mVR8NVvxuoGRAeoI1FWusAKRe9hH8nRCLrelA==", + "version": "16.2.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-16.2.7.tgz", + "integrity": "sha512-K10EE3qtSv4AoI3gnCNT80BbDNMK6UmpM8w0sd08hlNC4SCfzp+OFszV0AW29A5VK3zkbDQLJ6PL4wnNN4iuDQ==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.3", - "@angular-devkit/schematics": "16.2.3", + "@angular-devkit/core": "16.2.7", + "@angular-devkit/schematics": "16.2.7", "ansi-colors": "4.1.3", "inquirer": "8.2.4", "symbol-observable": "4.0.0", @@ -938,9 +932,9 @@ "dev": true }, "node_modules/@eslint/js": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", - "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", + "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1037,9 +1031,9 @@ ] }, "node_modules/@grpc/grpc-js": { - "version": "1.9.6", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.6.tgz", - "integrity": "sha512-yq3qTy23u++8zdvf+h4mz4ohDFi681JAkMZZPTKh8zmUVh0AKLisFlgxcn22FMNowXz15oJ6pqgwT7DJ+PdJvg==", + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.7.tgz", + "integrity": "sha512-yMaA/cIsRhGzW3ymCNpdlPcInXcovztlgu/rirThj2b87u3RzWUszliOqZ/pldy7yhmJPS8uwog+kZSTa4A0PQ==", "dependencies": { "@grpc/proto-loader": "^0.7.8", "@types/node": ">=12.12.47" @@ -1066,12 +1060,12 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", "minimatch": "^3.0.5" }, @@ -1093,9 +1087,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "node_modules/@ioredis/commands": { @@ -1488,6 +1482,26 @@ } } }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -1653,6 +1667,18 @@ "node": ">=8" } }, + "node_modules/@mobicoop/configuration-module": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@mobicoop/configuration-module/-/configuration-module-4.0.0.tgz", + "integrity": "sha512-Yd5ONDLwvEcolGYpg6EYLUNWQf8ClWT2UaYISBVWSOn37duFi0F3iuSq4W68JY2Y7ZkF3CalSht2fJVjU8rw0Q==", + "dependencies": { + "@songkeys/nestjs-redis": "^10.0.0", + "ioredis": "^5.3.2" + }, + "peerDependencies": { + "@nestjs/common": "^10.2.7" + } + }, "node_modules/@mobicoop/ddd-library": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@mobicoop/ddd-library/-/ddd-library-2.1.1.tgz", @@ -1712,20 +1738,21 @@ } }, "node_modules/@nestjs/cli": { - "version": "10.1.18", - "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.1.18.tgz", - "integrity": "sha512-jQtG47keLsACt7b4YwJbTBYRm90n82gJpMaiR1HGAyQ9pccbctjSYu592eT4bxqkUWxPgBE3mpNynXj7dWAfrw==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.2.0.tgz", + "integrity": "sha512-OMbn6A/YNu7QSk1nM8VucrtUwocaa0XEa9uoqRpw5Acvh/KIetvMHCn8L6yIBxiK7yvYiKa8q9U+RpLsKpKfgw==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.3", - "@angular-devkit/schematics": "16.2.3", - "@angular-devkit/schematics-cli": "16.2.3", + "@angular-devkit/core": "16.2.7", + "@angular-devkit/schematics": "16.2.7", + "@angular-devkit/schematics-cli": "16.2.7", "@nestjs/schematics": "^10.0.1", "chalk": "4.1.2", "chokidar": "3.5.3", "cli-table3": "0.6.3", "commander": "4.1.1", - "fork-ts-checker-webpack-plugin": "8.0.0", + "fork-ts-checker-webpack-plugin": "9.0.0", + "glob": "10.3.4", "inquirer": "8.2.6", "node-emoji": "1.11.0", "ora": "5.4.1", @@ -1737,14 +1764,14 @@ "tsconfig-paths": "4.2.0", "tsconfig-paths-webpack-plugin": "4.1.0", "typescript": "5.2.2", - "webpack": "5.88.2", + "webpack": "5.89.0", "webpack-node-externals": "3.0.0" }, "bin": { "nest": "bin/nest.js" }, "engines": { - "node": ">= 16" + "node": ">= 16.14" }, "peerDependencies": { "@swc/cli": "^0.1.62", @@ -1768,46 +1795,6 @@ "balanced-match": "^1.0.0" } }, - "node_modules/@nestjs/cli/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@nestjs/cli/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/@nestjs/cli/node_modules/glob": { - "version": "9.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", - "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "minimatch": "^8.0.2", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@nestjs/cli/node_modules/minimatch": { "version": "8.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", @@ -1823,6 +1810,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@nestjs/cli/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/@nestjs/cli/node_modules/rimraf": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", @@ -1841,51 +1837,22 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@nestjs/cli/node_modules/webpack": { - "version": "5.88.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", - "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", + "node_modules/@nestjs/cli/node_modules/rimraf/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", "dev": true, "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" }, "engines": { - "node": ">=10.13.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@nestjs/common": { @@ -2180,9 +2147,9 @@ } }, "node_modules/@nestjs/swagger": { - "version": "7.1.13", - "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.1.13.tgz", - "integrity": "sha512-aHfW0rDZZKTuPVSkxutBCB16lBy5vrsHVoRF5RvPtH7U2cm4Vf+OnfhxKKuG2g2Xocn9sDL+JAyVlY2VN3ytTw==", + "version": "7.1.14", + "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.1.14.tgz", + "integrity": "sha512-2Ol4S6qHeYVVmkshkWBM8E/qkmEqEOUj2QIewr0jLSyo30H7f3v81pJyks6pTLy4PK0LGUXojMvIfFIE3mmGQQ==", "dependencies": { "@nestjs/mapped-types": "2.0.2", "js-yaml": "4.1.0", @@ -2387,38 +2354,6 @@ "url": "https://opencollective.com/unts" } }, - "node_modules/@prisma/client": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.4.2.tgz", - "integrity": "sha512-2xsPaz4EaMKj1WS9iW6MlPhmbqtBsXAOeVttSePp8vTFTtvzh2hZbDgswwBdSCgPzmmwF+tLB259QzggvCmJqA==", - "hasInstallScript": true, - "dependencies": { - "@prisma/engines-version": "5.4.1-2.ac9d7041ed77bcc8a8dbd2ab6616b39013829574" - }, - "engines": { - "node": ">=16.13" - }, - "peerDependencies": { - "prisma": "*" - }, - "peerDependenciesMeta": { - "prisma": { - "optional": true - } - } - }, - "node_modules/@prisma/engines": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.4.2.tgz", - "integrity": "sha512-fqeucJ3LH0e1eyFdT0zRx+oETLancu5+n4lhiYECyEz6H2RDskPJHJYHkVc0LhkU4Uv7fuEnppKU3nVKNzMh8g==", - "devOptional": true, - "hasInstallScript": true - }, - "node_modules/@prisma/engines-version": { - "version": "5.4.1-2.ac9d7041ed77bcc8a8dbd2ab6616b39013829574", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.4.1-2.ac9d7041ed77bcc8a8dbd2ab6616b39013829574.tgz", - "integrity": "sha512-wvupDL4AA1vf4TQNANg7kR7y98ITqPsk6aacfBxZKtrJKRIsWjURHkZCGcQliHdqCiW/hGreO6d6ZuSv9MhdAA==" - }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -2655,9 +2590,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.38", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.38.tgz", - "integrity": "sha512-hXOtc0tuDHZPFwwhuBJXPbjemWtXnJjbvuuyNH2Y5Z6in+iXc63c4eXYDc7GGGqHy+iwYqAJMdaItqdnbcBKmg==", + "version": "4.17.39", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.39.tgz", + "integrity": "sha512-BiEUfAiGCOllomsRAZOiMFP7LAnrifHpt56pc4Z7l9K6ACyN06Ns1JLMBxwkfLOjJRlSf06NwWsT7yzfpaVpyQ==", "dev": true, "dependencies": { "@types/node": "*", @@ -2728,9 +2663,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", - "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "version": "20.8.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.8.tgz", + "integrity": "sha512-YRsdVxq6OaLfmR9Hy816IMp33xOBjfyOgUd77ehqg96CFywxAPbDbXvAsuN2KVg2HOT8Eh6uAfU+l4WffwPVrQ==", "dependencies": { "undici-types": "~5.25.1" } @@ -2805,12 +2740,6 @@ "@types/superagent": "*" } }, - "node_modules/@types/uuid": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.6.tgz", - "integrity": "sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==", - "dev": true - }, "node_modules/@types/validator": { "version": "13.11.5", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.5.tgz", @@ -2832,16 +2761,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.8.0.tgz", - "integrity": "sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.0.tgz", + "integrity": "sha512-lgX7F0azQwRPB7t7WAyeHWVfW1YJ9NIgd9mvGhfQpRY56X6AVf8mwM8Wol+0z4liE7XX3QOt8MN1rUKCfSjRIA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/type-utils": "6.8.0", - "@typescript-eslint/utils": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", + "@typescript-eslint/scope-manager": "6.9.0", + "@typescript-eslint/type-utils": "6.9.0", + "@typescript-eslint/utils": "6.9.0", + "@typescript-eslint/visitor-keys": "6.9.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -2867,15 +2796,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.8.0.tgz", - "integrity": "sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.0.tgz", + "integrity": "sha512-GZmjMh4AJ/5gaH4XF2eXA8tMnHWP+Pm1mjQR2QN4Iz+j/zO04b9TOvJYOX2sCNIQHtRStKTxRY1FX7LhpJT4Gw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/typescript-estree": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", + "@typescript-eslint/scope-manager": "6.9.0", + "@typescript-eslint/types": "6.9.0", + "@typescript-eslint/typescript-estree": "6.9.0", + "@typescript-eslint/visitor-keys": "6.9.0", "debug": "^4.3.4" }, "engines": { @@ -2895,13 +2824,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", - "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.0.tgz", + "integrity": "sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0" + "@typescript-eslint/types": "6.9.0", + "@typescript-eslint/visitor-keys": "6.9.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2912,13 +2841,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.8.0.tgz", - "integrity": "sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.0.tgz", + "integrity": "sha512-XXeahmfbpuhVbhSOROIzJ+b13krFmgtc4GlEuu1WBT+RpyGPIA4Y/eGnXzjbDj5gZLzpAXO/sj+IF/x2GtTMjQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.8.0", - "@typescript-eslint/utils": "6.8.0", + "@typescript-eslint/typescript-estree": "6.9.0", + "@typescript-eslint/utils": "6.9.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -2939,9 +2868,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", - "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz", + "integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2952,13 +2881,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", - "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.0.tgz", + "integrity": "sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", + "@typescript-eslint/types": "6.9.0", + "@typescript-eslint/visitor-keys": "6.9.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2979,17 +2908,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.8.0.tgz", - "integrity": "sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.0.tgz", + "integrity": "sha512-5Wf+Jsqya7WcCO8me504FBigeQKVLAMPmUzYgDbWchINNh1KJbxCgVya3EQ2MjvJMVeXl3pofRmprqX6mfQkjQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/typescript-estree": "6.8.0", + "@typescript-eslint/scope-manager": "6.9.0", + "@typescript-eslint/types": "6.9.0", + "@typescript-eslint/typescript-estree": "6.9.0", "semver": "^7.5.4" }, "engines": { @@ -3004,12 +2933,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", - "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz", + "integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/types": "6.9.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -3020,6 +2949,12 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/@webassemblyjs/ast": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", @@ -3884,12 +3819,13 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3916,9 +3852,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001551", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001551.tgz", - "integrity": "sha512-vtBAez47BoGMMzlbYhfXrMV1kvRF2WP/lqiMuDu1Sb4EE4LKEgjopFDSRtZfdVnslNRpOqV/woE+Xgrwj6VQlg==", + "version": "1.0.30001554", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001554.tgz", + "integrity": "sha512-A2E3U//MBwbJVzebddm1YfNp7Nud5Ip+IPn4BozBmn4KqVX7AvluoIDFWjsv5OkGnKUXQVmMSoMKLa3ScCblcQ==", "dev": true, "funding": [ { @@ -4573,6 +4509,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/default-browser/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, "node_modules/default-browser/node_modules/strip-final-newline": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", @@ -4597,6 +4539,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/define-lazy-prop": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", @@ -4748,9 +4703,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.559", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.559.tgz", - "integrity": "sha512-iS7KhLYCSJbdo3rUSkhDTVuFNCV34RKs2UaB9Ecr7VlqzjjWW//0nfsFF5dtDmyXlZQaDYYtID5fjtC/6lpRug==", + "version": "1.4.566", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.566.tgz", + "integrity": "sha512-mv+fAy27uOmTVlUULy15U3DVJ+jg+8iyKH1bpwboCRhtDC69GKf1PPTZvEIhCyDr81RFqfxZJYrbgp933a1vtg==", "dev": true }, "node_modules/emittery": { @@ -4841,18 +4796,19 @@ } }, "node_modules/eslint": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", - "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", + "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.51.0", - "@humanwhocodes/config-array": "^0.11.11", + "@eslint/js": "8.52.0", + "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -5114,6 +5070,12 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/execa/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -5439,6 +5401,26 @@ "node": ">=12.0.0" } }, + "node_modules/flat-cache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/flat-cache/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -5494,21 +5476,10 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/fork-ts-checker-webpack-plugin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-8.0.0.tgz", - "integrity": "sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.0.tgz", + "integrity": "sha512-Kw3JjsfGs0piB0V2Em8gCuo51O3p4KyCOK0Tn8X57oq2mSNBrMmONALRBw5frcmWsOVU7iELXXsJ+FVxJeQuhA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.16.7", @@ -5603,6 +5574,20 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -5629,14 +5614,14 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5664,20 +5649,22 @@ } }, "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "version": "10.3.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.4.tgz", + "integrity": "sha512-6LFElP3A+i/Q8XQKEvZjkEWEOTgAIALR9AO2rwT8bgPhDd1anmqDJDZ6lLddI4ehxxxR1S5RIqKe1uapMQfYaQ==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/cjs/src/bin.js" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -5701,6 +5688,30 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/globals": { "version": "13.23.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", @@ -5736,6 +5747,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -5748,14 +5770,6 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -5773,6 +5787,17 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", @@ -5795,6 +5820,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/hexoid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", @@ -6032,12 +6068,12 @@ } }, "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6451,6 +6487,26 @@ } } }, + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/jest-diff": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", @@ -6750,6 +6806,26 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/jest-snapshot": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", @@ -7259,12 +7335,11 @@ } }, "node_modules/minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", - "dev": true, + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/mkdirp": { @@ -7419,9 +7494,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.0.tgz", - "integrity": "sha512-HQ4J+ic8hKrgIt3mqk6cVOVrW2ozL4KdvHlqpBv9vDYWx9ysAgENAdvy4FoGF+KFdhR7nQTNm5J0ctAeOwn+3g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7676,14 +7751,6 @@ "node": "14 || >=16.14" } }, - "node_modules/path-scurry/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/path-to-regexp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", @@ -7860,22 +7927,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/prisma": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.4.2.tgz", - "integrity": "sha512-GDMZwZy7mysB2oXU+angQqJ90iaPFdD0rHaZNkn+dio5NRkGLmMqmXs31//tg/qXT3iB0cTQwnGGQNuirhSTZg==", - "devOptional": true, - "hasInstallScript": true, - "dependencies": { - "@prisma/engines": "5.4.2" - }, - "bin": { - "prisma": "build/index.js" - }, - "engines": { - "node": ">=16.13" - } - }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -8209,6 +8260,12 @@ "node": ">=8" } }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -8279,14 +8336,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rimraf/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/run-applescript": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", @@ -8498,6 +8547,20 @@ "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -8539,6 +8602,26 @@ "node": ">=4" } }, + "node_modules/shelljs/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -8553,10 +8636,15 @@ } }, "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/sisteransi": { "version": "1.0.5", @@ -8956,6 +9044,26 @@ "node": ">=8" } }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -9455,7 +9563,6 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", "dev": true, - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.0", @@ -9521,7 +9628,6 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, - "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -9535,7 +9641,6 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "peer": true, "engines": { "node": ">=4.0" } @@ -9636,6 +9741,12 @@ "node": ">=8.12.0" } }, + "node_modules/windows-release/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -9688,6 +9799,12 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index aafb2d5..25ba444 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "dependencies": { "@grpc/grpc-js": "^1.9.6", "@grpc/proto-loader": "^0.7.10", + "@mobicoop/configuration-module": "^4.0.0", "@mobicoop/ddd-library": "^2.1.1", "@mobicoop/health-module": "^2.3.1", "@mobicoop/message-broker-module": "^2.1.1", @@ -37,14 +38,10 @@ "@nestjs/microservices": "^10.2.7", "@nestjs/platform-express": "^10.2.7", "@nestjs/terminus": "^10.1.1", - "@songkeys/nestjs-redis": "^10.0.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", - "ioredis": "^5.3.2", "reflect-metadata": "^0.1.13", - "rimraf": "^5.0.5", - "rxjs": "^7.8.1", - "uuid": "^9.0.1" + "rimraf": "^5.0.5" }, "devDependencies": { "@nestjs/cli": "^10.1.18", @@ -54,7 +51,6 @@ "@types/jest": "29.5.6", "@types/node": "^20.8.7", "@types/supertest": "^2.0.15", - "@types/uuid": "^9.0.6", "@typescript-eslint/eslint-plugin": "^6.8.0", "@typescript-eslint/parser": "^6.8.0", "dotenv-cli": "^7.3.0", diff --git a/src/app.module.ts b/src/app.module.ts index da0a360..644e029 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -4,6 +4,10 @@ import { Module } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { HEALTH_CRITICAL_LOGGING_KEY, SERVICE_NAME } from './app.constants'; import { MessagePublisherPort } from '@mobicoop/ddd-library'; +import { + ConfigurationModuleOptions, + ConfigurationModule as ConfigurationModulePackage, +} from '@mobicoop/configuration-module'; import { MESSAGE_PUBLISHER } from '@modules/messager/messager.di-tokens'; import { ConfigurationModule } from '@modules/configuration/configuration.module'; import { EventEmitterModule } from '@nestjs/event-emitter'; @@ -11,7 +15,6 @@ import brokerConfig from './config/broker.config'; import carpoolConfig from './config/carpool.config'; import paginationConfig from './config/pagination.config'; import serviceConfig from './config/service.config'; -import { RedisModule, RedisModuleOptions } from '@songkeys/nestjs-redis'; import redisConfig from './config/redis.config'; import { Transport } from '@nestjs/microservices'; @@ -49,18 +52,16 @@ import { Transport } from '@nestjs/microservices'; ], }), }), - RedisModule.forRootAsync({ + ConfigurationModulePackage.forRootAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: async ( configService: ConfigService, - ): Promise => { + ): Promise => { return { - config: { - host: configService.get('redis.host') as string, - port: configService.get('redis.port') as number, - password: configService.get('redis.password'), - }, + host: configService.get('redis.host') as string, + port: configService.get('redis.port') as number, + password: configService.get('redis.password'), }; }, }), diff --git a/src/config/carpool.config.ts b/src/config/carpool.config.ts index 51f54bb..de03b1a 100644 --- a/src/config/carpool.config.ts +++ b/src/config/carpool.config.ts @@ -1,5 +1,13 @@ import { registerAs } from '@nestjs/config'; +export interface CarpoolConfig { + departureTimeMargin: number; + role: string; + seatsProposed: number; + seatsRequested: number; + strictFrequency: boolean; +} + export default registerAs('carpool', () => ({ departureTimeMargin: process.env.DEPARTURE_TIME_MARGIN ? parseInt(process.env.DEPARTURE_TIME_MARGIN, 10) diff --git a/src/config/pagination.config.ts b/src/config/pagination.config.ts index e7b9ded..ddf412f 100644 --- a/src/config/pagination.config.ts +++ b/src/config/pagination.config.ts @@ -1,5 +1,9 @@ import { registerAs } from '@nestjs/config'; +export interface PaginationConfig { + perPage: number; +} + export default registerAs('pagination', () => ({ perPage: process.env.PER_PAGE ? parseInt(process.env.PER_PAGE, 10) : 10, })); diff --git a/src/modules/configuration/configuration.mapper.ts b/src/modules/configuration/configuration.mapper.ts index 726f814..51c38d1 100644 --- a/src/modules/configuration/configuration.mapper.ts +++ b/src/modules/configuration/configuration.mapper.ts @@ -1,55 +1,20 @@ -import { Mapper } from '@mobicoop/ddd-library'; import { Injectable } from '@nestjs/common'; -import { ConfigurationEntity } from './core/domain/configuration.entity'; import { ConfigurationResponseDto } from './interface/dtos/configuration.response.dto'; -import { ConfigurationDomain } from './core/domain/configuration.types'; import { - ConfigurationReadModel, - ConfigurationWriteModel, -} from './infrastructure/configuration.repository'; -import { v4 } from 'uuid'; + ConfigurationIdentifier, + ConfigurationValue, +} from '@mobicoop/configuration-module'; @Injectable() -export class ConfigurationMapper - implements - Mapper< - ConfigurationEntity, - ConfigurationReadModel, - ConfigurationWriteModel, - ConfigurationResponseDto - > -{ - toPersistence = (entity: ConfigurationEntity): ConfigurationWriteModel => { - const copy = entity.getProps(); - const record: ConfigurationWriteModel = { - key: `${copy.identifier.domain}:${copy.identifier.key}`, - value: copy.value, - }; - return record; - }; - - toDomain = (record: ConfigurationReadModel): ConfigurationEntity => { - const entity = new ConfigurationEntity({ - id: v4(), - createdAt: new Date(), - updatedAt: new Date(), - props: { - identifier: { - domain: record.key.split(':')[0] as ConfigurationDomain, - key: record.key.split(':')[1], - }, - value: record.value, - }, - }); - return entity; - }; - - toResponse = (entity: ConfigurationEntity): ConfigurationResponseDto => { - const props = entity.getProps(); - const response = new ConfigurationResponseDto(entity); - response.domain = props.identifier.domain; - response.key = props.identifier.key; - response.value = props.value; +export class ConfigurationMapper { + toResponse = ( + configurationIdentifier: ConfigurationIdentifier, + configurationValue: ConfigurationValue, + ): ConfigurationResponseDto => { + const response = new ConfigurationResponseDto(); + response.domain = configurationIdentifier.domain; + response.key = configurationIdentifier.key; + response.value = configurationValue; return response; }; } diff --git a/src/modules/configuration/configuration.module.ts b/src/modules/configuration/configuration.module.ts index 753f41a..2dba244 100644 --- a/src/modules/configuration/configuration.module.ts +++ b/src/modules/configuration/configuration.module.ts @@ -7,7 +7,7 @@ import { GetConfigurationQueryHandler } from './core/application/queries/get-con import { ConfigurationMapper } from './configuration.mapper'; import { CONFIGURATION_REPOSITORY } from './configuration.di-tokens'; import { PopulateService } from './core/application/services/populate.service'; -import { ConfigurationRepository } from './infrastructure/configuration.repository'; +import { ConfigurationRepository } from '@mobicoop/configuration-module'; const grpcControllers = [ GetConfigurationGrpcController, diff --git a/src/modules/configuration/core/application/commands/set-configuration/set-configuration.service.ts b/src/modules/configuration/core/application/commands/set-configuration/set-configuration.service.ts index ae488cb..dc73828 100644 --- a/src/modules/configuration/core/application/commands/set-configuration/set-configuration.service.ts +++ b/src/modules/configuration/core/application/commands/set-configuration/set-configuration.service.ts @@ -2,18 +2,23 @@ import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'; import { Inject } from '@nestjs/common'; import { SetConfigurationCommand } from './set-configuration.command'; import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens'; -import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types'; -import { ConfigurationRepositoryPort } from '../../ports/configuration.repository.port'; +import { + ConfigurationDomain, + ConfigurationIdentifier, + SetConfigurationRepositoryPort, +} from '@mobicoop/configuration-module'; @CommandHandler(SetConfigurationCommand) export class SetConfigurationService implements ICommandHandler { constructor( @Inject(CONFIGURATION_REPOSITORY) - private readonly configurationRepository: ConfigurationRepositoryPort, + private readonly configurationRepository: SetConfigurationRepositoryPort, ) {} - async execute(command: SetConfigurationCommand): Promise { - await this.configurationRepository.set( + async execute( + command: SetConfigurationCommand, + ): Promise { + return await this.configurationRepository.set( { domain: command.domain as ConfigurationDomain, key: command.key, diff --git a/src/modules/configuration/core/application/ports/configuration.repository.port.ts b/src/modules/configuration/core/application/ports/configuration.repository.port.ts deleted file mode 100644 index 0485ca6..0000000 --- a/src/modules/configuration/core/application/ports/configuration.repository.port.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ConfigurationEntity } from '../../domain/configuration.entity'; -import { - ConfigurationIdentifier, - ConfigurationValue, -} from '../../domain/configuration.types'; - -export interface ConfigurationRepositoryPort { - get(identifier: ConfigurationIdentifier): Promise; - set( - identifier: ConfigurationIdentifier, - value: ConfigurationValue, - ): Promise; -} diff --git a/src/modules/configuration/core/application/queries/get-configuration/get-configuration.query-handler.ts b/src/modules/configuration/core/application/queries/get-configuration/get-configuration.query-handler.ts index d71a463..ed7bcc0 100644 --- a/src/modules/configuration/core/application/queries/get-configuration/get-configuration.query-handler.ts +++ b/src/modules/configuration/core/application/queries/get-configuration/get-configuration.query-handler.ts @@ -2,17 +2,19 @@ import { IQueryHandler, QueryHandler } from '@nestjs/cqrs'; import { GetConfigurationQuery } from './get-configuration.query'; import { Inject } from '@nestjs/common'; import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens'; -import { ConfigurationEntity } from '@modules/configuration/core/domain/configuration.entity'; -import { ConfigurationRepositoryPort } from '../../ports/configuration.repository.port'; -import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types'; +import { + ConfigurationDomain, + ConfigurationValue, + GetConfigurationRepositoryPort, +} from '@mobicoop/configuration-module'; @QueryHandler(GetConfigurationQuery) export class GetConfigurationQueryHandler implements IQueryHandler { constructor( @Inject(CONFIGURATION_REPOSITORY) - private readonly configurationRepository: ConfigurationRepositoryPort, + private readonly configurationRepository: GetConfigurationRepositoryPort, ) {} - async execute(query: GetConfigurationQuery): Promise { + async execute(query: GetConfigurationQuery): Promise { return await this.configurationRepository.get({ domain: query.domain as ConfigurationDomain, key: query.key, diff --git a/src/modules/configuration/core/application/services/populate.service.ts b/src/modules/configuration/core/application/services/populate.service.ts index 6f93db3..3f3390a 100644 --- a/src/modules/configuration/core/application/services/populate.service.ts +++ b/src/modules/configuration/core/application/services/populate.service.ts @@ -1,19 +1,23 @@ +import { + ConfigurationDomain, + GetConfigurationRepositoryPort, + NotFoundException, + SetConfigurationRepositoryPort, +} from '@mobicoop/configuration-module'; import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens'; import { Inject, Injectable, OnApplicationBootstrap } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import { ConfigurationRepositoryPort } from '../ports/configuration.repository.port'; -import { - CarpoolConfig, - ConfigurationDomain, - PaginationConfig, -} from '../../domain/configuration.types'; -import { NotFoundException } from '@mobicoop/ddd-library'; + +import { CarpoolConfig } from '@src/config/carpool.config'; +import { PaginationConfig } from '@src/config/pagination.config'; @Injectable() export class PopulateService implements OnApplicationBootstrap { constructor( @Inject(CONFIGURATION_REPOSITORY) - private readonly configurationRepository: ConfigurationRepositoryPort, + private readonly getConfigurationRepository: GetConfigurationRepositoryPort, + @Inject(CONFIGURATION_REPOSITORY) + private readonly setConfigurationRepository: SetConfigurationRepositoryPort, private readonly configService: ConfigService, ) {} @@ -42,13 +46,13 @@ export class PopulateService implements OnApplicationBootstrap { let key: keyof typeof config; for (key in config) { try { - await this.configurationRepository.get({ + await this.getConfigurationRepository.get({ domain, key, }); } catch (error: any) { if (error instanceof NotFoundException) { - this.configurationRepository.set( + this.setConfigurationRepository.set( { domain, key, diff --git a/src/modules/configuration/core/domain/configuration.entity.ts b/src/modules/configuration/core/domain/configuration.entity.ts deleted file mode 100644 index b611b96..0000000 --- a/src/modules/configuration/core/domain/configuration.entity.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { AggregateRoot, AggregateID } from '@mobicoop/ddd-library'; -import { v4 } from 'uuid'; -import { - ConfigurationProps, - CreateConfigurationProps, -} from './configuration.types'; - -export class ConfigurationEntity extends AggregateRoot { - protected readonly _id: AggregateID; - - static create = (create: CreateConfigurationProps): ConfigurationEntity => { - const id = v4(); - const props: ConfigurationProps = { ...create }; - const configuration = new ConfigurationEntity({ id, props }); - return configuration; - }; - - validate(): void { - // entity business rules validation to protect it's invariant before saving entity to a database - } -} diff --git a/src/modules/configuration/core/domain/configuration.types.ts b/src/modules/configuration/core/domain/configuration.types.ts deleted file mode 100644 index f54b4a2..0000000 --- a/src/modules/configuration/core/domain/configuration.types.ts +++ /dev/null @@ -1,36 +0,0 @@ -// All properties that a Configuration has -export interface ConfigurationProps { - identifier: ConfigurationIdentifier; - value: ConfigurationValue; -} - -// Properties that are needed for a Configuration creation -export interface CreateConfigurationProps { - identifier: ConfigurationIdentifier; - value: ConfigurationValue; -} - -export enum ConfigurationDomain { - CARPOOL = 'CARPOOL', - PAGINATION = 'PAGINATION', -} - -export type ConfigurationIdentifier = { - domain: ConfigurationDomain; - key: ConfigurationKey; -}; - -export type ConfigurationKey = string; -export type ConfigurationValue = string; - -export interface CarpoolConfig { - departureTimeMargin: number; - role: string; - seatsProposed: number; - seatsRequested: number; - strictFrequency: boolean; -} - -export interface PaginationConfig { - perPage: number; -} diff --git a/src/modules/configuration/infrastructure/configuration.repository.ts b/src/modules/configuration/infrastructure/configuration.repository.ts deleted file mode 100644 index 8a29d5c..0000000 --- a/src/modules/configuration/infrastructure/configuration.repository.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { ConfigurationRepositoryPort } from '../core/application/ports/configuration.repository.port'; -import { InjectRedis } from '@songkeys/nestjs-redis'; -import { Redis } from 'ioredis'; -import { - ConfigurationIdentifier, - ConfigurationValue, -} from '../core/domain/configuration.types'; -import { ConfigurationEntity } from '../core/domain/configuration.entity'; -import { ConfigurationMapper } from '../configuration.mapper'; -import { NotFoundException } from '@mobicoop/ddd-library'; - -export type ConfigurationReadModel = { - key: string; - value: string; -}; -export type ConfigurationWriteModel = ConfigurationReadModel; - -@Injectable() -export class ConfigurationRepository implements ConfigurationRepositoryPort { - constructor( - @InjectRedis() private readonly redis: Redis, - private readonly mapper: ConfigurationMapper, - ) {} - - get = async ( - identifier: ConfigurationIdentifier, - ): Promise => { - const key: string = `${identifier.domain}:${identifier.key}`; - const value: ConfigurationValue | null = await this.redis.get(key); - if (!value) - throw new NotFoundException( - `Configuration item not found for key ${key}`, - ); - return this.mapper.toDomain({ - key, - value, - }); - }; - - set = async ( - identifier: ConfigurationIdentifier, - value: ConfigurationValue, - ): Promise => { - await this.redis.set(`${identifier.domain}:${identifier.key}`, value); - }; -} diff --git a/src/modules/configuration/interface/dtos/configuration.response.dto.ts b/src/modules/configuration/interface/dtos/configuration.response.dto.ts index 8b7a7b2..56c46eb 100644 --- a/src/modules/configuration/interface/dtos/configuration.response.dto.ts +++ b/src/modules/configuration/interface/dtos/configuration.response.dto.ts @@ -1,6 +1,4 @@ -import { ResponseBase } from '@mobicoop/ddd-library'; - -export class ConfigurationResponseDto extends ResponseBase { +export class ConfigurationResponseDto { domain: string; key: string; value: string; diff --git a/src/modules/configuration/interface/grpc-controllers/dtos/get-configuration.request.dto.ts b/src/modules/configuration/interface/grpc-controllers/dtos/get-configuration.request.dto.ts index 65aefd6..20a636c 100644 --- a/src/modules/configuration/interface/grpc-controllers/dtos/get-configuration.request.dto.ts +++ b/src/modules/configuration/interface/grpc-controllers/dtos/get-configuration.request.dto.ts @@ -1,4 +1,4 @@ -import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types'; +import { ConfigurationDomain } from '@mobicoop/configuration-module'; import { IsEnum, IsNotEmpty, IsString } from 'class-validator'; export class GetConfigurationRequestDto { diff --git a/src/modules/configuration/interface/grpc-controllers/dtos/set-configuration.request.dto.ts b/src/modules/configuration/interface/grpc-controllers/dtos/set-configuration.request.dto.ts index c6a0b80..98ba4e9 100644 --- a/src/modules/configuration/interface/grpc-controllers/dtos/set-configuration.request.dto.ts +++ b/src/modules/configuration/interface/grpc-controllers/dtos/set-configuration.request.dto.ts @@ -1,4 +1,4 @@ -import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types'; +import { ConfigurationDomain } from '@mobicoop/configuration-module'; import { IsEnum, IsNotEmpty, IsString } from 'class-validator'; export class SetConfigurationRequestDto { diff --git a/src/modules/configuration/interface/grpc-controllers/get-configuration.grpc.controller.ts b/src/modules/configuration/interface/grpc-controllers/get-configuration.grpc.controller.ts index 90bab7b..80014c6 100644 --- a/src/modules/configuration/interface/grpc-controllers/get-configuration.grpc.controller.ts +++ b/src/modules/configuration/interface/grpc-controllers/get-configuration.grpc.controller.ts @@ -1,15 +1,17 @@ import { Controller, UsePipes } from '@nestjs/common'; import { QueryBus } from '@nestjs/cqrs'; import { GrpcMethod, RpcException } from '@nestjs/microservices'; -import { NotFoundException } from '@mobicoop/ddd-library'; -import { RpcExceptionCode } from '@mobicoop/ddd-library'; -import { RpcValidationPipe } from '@mobicoop/ddd-library'; import { GRPC_SERVICE_NAME } from '@src/app.constants'; import { ConfigurationMapper } from '@modules/configuration/configuration.mapper'; import { GetConfigurationRequestDto } from './dtos/get-configuration.request.dto'; import { ConfigurationResponseDto } from '../dtos/configuration.response.dto'; -import { ConfigurationEntity } from '@modules/configuration/core/domain/configuration.entity'; import { GetConfigurationQuery } from '@modules/configuration/core/application/queries/get-configuration/get-configuration.query'; +import { + NotFoundException, + RpcExceptionCode, + RpcValidationPipe, +} from '@mobicoop/ddd-library'; +import { ConfigurationValue } from '@mobicoop/configuration-module'; @UsePipes( new RpcValidationPipe({ @@ -29,10 +31,11 @@ export class GetConfigurationGrpcController { data: GetConfigurationRequestDto, ): Promise { try { - const configuration: ConfigurationEntity = await this.queryBus.execute( - new GetConfigurationQuery(data.domain, data.key), - ); - return this.mapper.toResponse(configuration); + const configurationValue: ConfigurationValue = + await this.queryBus.execute( + new GetConfigurationQuery(data.domain, data.key), + ); + return this.mapper.toResponse(data, configurationValue); } catch (e) { if (e instanceof NotFoundException) { throw new RpcException({ diff --git a/src/modules/configuration/interface/grpc-controllers/set-configuration.grpc.controller.ts b/src/modules/configuration/interface/grpc-controllers/set-configuration.grpc.controller.ts index 3875c98..697bd0d 100644 --- a/src/modules/configuration/interface/grpc-controllers/set-configuration.grpc.controller.ts +++ b/src/modules/configuration/interface/grpc-controllers/set-configuration.grpc.controller.ts @@ -1,11 +1,11 @@ import { Controller, UsePipes } from '@nestjs/common'; import { CommandBus } from '@nestjs/cqrs'; import { GrpcMethod, RpcException } from '@nestjs/microservices'; -import { RpcExceptionCode } from '@mobicoop/ddd-library'; -import { RpcValidationPipe } from '@mobicoop/ddd-library'; +import { RpcExceptionCode, RpcValidationPipe } from '@mobicoop/ddd-library'; import { GRPC_SERVICE_NAME } from '@src/app.constants'; import { SetConfigurationRequestDto } from './dtos/set-configuration.request.dto'; import { SetConfigurationCommand } from '@modules/configuration/core/application/commands/set-configuration/set-configuration.command'; +import { ConfigurationIdentifier } from '@mobicoop/configuration-module'; @UsePipes( new RpcValidationPipe({ @@ -20,11 +20,13 @@ export class SetConfigurationGrpcController { @GrpcMethod(GRPC_SERVICE_NAME, 'Set') async set( setConfigurationRequestDto: SetConfigurationRequestDto, - ): Promise { + ): Promise { try { - await this.commandBus.execute( - new SetConfigurationCommand(setConfigurationRequestDto), - ); + const configurationIdentifier: ConfigurationIdentifier = + await this.commandBus.execute( + new SetConfigurationCommand(setConfigurationRequestDto), + ); + return configurationIdentifier; } catch (error: any) { throw new RpcException({ code: RpcExceptionCode.UNKNOWN, diff --git a/src/modules/configuration/tests/unit/configuration.mapper.spec.ts b/src/modules/configuration/tests/unit/configuration.mapper.spec.ts index 2345033..a622287 100644 --- a/src/modules/configuration/tests/unit/configuration.mapper.spec.ts +++ b/src/modules/configuration/tests/unit/configuration.mapper.spec.ts @@ -1,31 +1,8 @@ +import { ConfigurationDomain } from '@mobicoop/configuration-module'; import { ConfigurationMapper } from '@modules/configuration/configuration.mapper'; -import { ConfigurationEntity } from '@modules/configuration/core/domain/configuration.entity'; -import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types'; -import { - ConfigurationReadModel, - ConfigurationWriteModel, -} from '@modules/configuration/infrastructure/configuration.repository'; import { ConfigurationResponseDto } from '@modules/configuration/interface/dtos/configuration.response.dto'; import { Test } from '@nestjs/testing'; -const now = new Date('2023-06-21 06:00:00'); -const configurationEntity: ConfigurationEntity = new ConfigurationEntity({ - id: 'c160cf8c-f057-4962-841f-3ad68346df44', - props: { - identifier: { - domain: ConfigurationDomain.CARPOOL, - key: 'seatsProposed', - }, - value: '3', - }, - createdAt: now, - updatedAt: now, -}); -const configurationReadModel: ConfigurationReadModel = { - key: 'AD:seatsProposed', - value: '4', -}; - describe('Configuration Mapper', () => { let configurationMapper: ConfigurationMapper; @@ -40,22 +17,16 @@ describe('Configuration Mapper', () => { expect(configurationMapper).toBeDefined(); }); - it('should map domain entity to persistence data', async () => { - const mapped: ConfigurationWriteModel = - configurationMapper.toPersistence(configurationEntity); + it('should map configuration to response', async () => { + const mapped: ConfigurationResponseDto = configurationMapper.toResponse( + { + domain: ConfigurationDomain.CARPOOL, + key: 'seatsProposed', + }, + '3', + ); + expect(mapped.domain).toBe('CARPOOL'); + expect(mapped.key).toBe('seatsProposed'); expect(mapped.value).toBe('3'); }); - - it('should map persisted data to domain entity', async () => { - const mapped: ConfigurationEntity = configurationMapper.toDomain( - configurationReadModel, - ); - expect(mapped.getProps().value).toBe('4'); - }); - - it('should map domain entity to response', async () => { - const mapped: ConfigurationResponseDto = - configurationMapper.toResponse(configurationEntity); - expect(mapped.id).toBe('c160cf8c-f057-4962-841f-3ad68346df44'); - }); }); diff --git a/src/modules/configuration/tests/unit/core/configuration.entity.spec.ts b/src/modules/configuration/tests/unit/core/configuration.entity.spec.ts deleted file mode 100644 index a7a429a..0000000 --- a/src/modules/configuration/tests/unit/core/configuration.entity.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ConfigurationEntity } from '@modules/configuration/core/domain/configuration.entity'; -import { - CreateConfigurationProps, - ConfigurationDomain, -} from '@modules/configuration/core/domain/configuration.types'; - -const createConfigurationProps: CreateConfigurationProps = { - identifier: { - domain: ConfigurationDomain.CARPOOL, - key: 'seatsProposed', - }, - value: '3', -}; - -describe('Configuration entity create', () => { - it('should create a new configuration entity', async () => { - const configurationEntity: ConfigurationEntity = ConfigurationEntity.create( - createConfigurationProps, - ); - expect(configurationEntity.id.length).toBe(36); - expect(configurationEntity.getProps().value).toBe('3'); - }); -}); diff --git a/src/modules/configuration/tests/unit/core/get-configuration.query-handler.spec.ts b/src/modules/configuration/tests/unit/core/get-configuration.query-handler.spec.ts index 4171af4..cff74a2 100644 --- a/src/modules/configuration/tests/unit/core/get-configuration.query-handler.spec.ts +++ b/src/modules/configuration/tests/unit/core/get-configuration.query-handler.spec.ts @@ -1,26 +1,16 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { ConfigurationEntity } from '@modules/configuration/core/domain/configuration.entity'; -import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types'; import { GetConfigurationQueryHandler } from '@modules/configuration/core/application/queries/get-configuration/get-configuration.query-handler'; import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens'; import { GetConfigurationQuery } from '@modules/configuration/core/application/queries/get-configuration/get-configuration.query'; +import { + ConfigurationDomain, + ConfigurationValue, +} from '@mobicoop/configuration-module'; -const now = new Date('2023-06-21 06:00:00'); -const configuration: ConfigurationEntity = new ConfigurationEntity({ - id: 'c160cf8c-f057-4962-841f-3ad68346df44', - props: { - identifier: { - domain: ConfigurationDomain.CARPOOL, - key: 'seatsProposed', - }, - value: '3', - }, - createdAt: now, - updatedAt: now, -}); +const configurationValue: ConfigurationValue = '3'; const mockConfigurationRepository = { - get: jest.fn().mockImplementation(() => configuration), + get: jest.fn().mockImplementation(() => configurationValue), }; describe('Get Configuration Query Handler', () => { @@ -47,14 +37,14 @@ describe('Get Configuration Query Handler', () => { }); describe('execution', () => { - it('should return a configuration item', async () => { + it('should return a configuration value', async () => { const getConfigurationQuery = new GetConfigurationQuery( ConfigurationDomain.CARPOOL, 'seatsProposed', ); - const configuration: ConfigurationEntity = + const configurationValue: ConfigurationValue = await getConfigurationQueryHandler.execute(getConfigurationQuery); - expect(configuration.getProps().value).toBe('3'); + expect(configurationValue).toBe('3'); }); }); }); diff --git a/src/modules/configuration/tests/unit/core/populate.service.spec.ts b/src/modules/configuration/tests/unit/core/populate.service.spec.ts index b1d6923..4e76b67 100644 --- a/src/modules/configuration/tests/unit/core/populate.service.spec.ts +++ b/src/modules/configuration/tests/unit/core/populate.service.spec.ts @@ -1,29 +1,13 @@ -import { NotFoundException } from '@mobicoop/ddd-library'; +import { NotFoundException } from '@mobicoop/configuration-module'; import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens'; import { PopulateService } from '@modules/configuration/core/application/services/populate.service'; -import { ConfigurationEntity } from '@modules/configuration/core/domain/configuration.entity'; -import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types'; import { ConfigService } from '@nestjs/config'; import { Test, TestingModule } from '@nestjs/testing'; const mockConfigurationRepository = { get: jest .fn() - .mockImplementationOnce( - () => - new ConfigurationEntity({ - id: '001199d4-7187-4e83-a044-12159cba2e33', - props: { - identifier: { - domain: ConfigurationDomain.CARPOOL, - key: 'someKey', - }, - value: 'someValue', - }, - createdAt: new Date('2023-10-23'), - updatedAt: new Date('2023-10-23'), - }), - ) + .mockImplementationOnce(() => 'someValue') .mockImplementationOnce(() => { throw new NotFoundException('Configuration not found'); }), diff --git a/src/modules/configuration/tests/unit/core/set-configuration.service.spec.ts b/src/modules/configuration/tests/unit/core/set-configuration.service.spec.ts index 35aec9b..bdbcf27 100644 --- a/src/modules/configuration/tests/unit/core/set-configuration.service.spec.ts +++ b/src/modules/configuration/tests/unit/core/set-configuration.service.spec.ts @@ -1,10 +1,9 @@ import { Test, TestingModule } from '@nestjs/testing'; import { SetConfigurationRequestDto } from '@modules/configuration/interface/grpc-controllers/dtos/set-configuration.request.dto'; -import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types'; import { SetConfigurationService } from '@modules/configuration/core/application/commands/set-configuration/set-configuration.service'; import { CONFIGURATION_REPOSITORY } from '@modules/configuration/configuration.di-tokens'; import { SetConfigurationCommand } from '@modules/configuration/core/application/commands/set-configuration/set-configuration.command'; -import { ConfigurationEntity } from '@modules/configuration/core/domain/configuration.entity'; +import { ConfigurationDomain } from '@mobicoop/configuration-module'; const setConfigurationRequest: SetConfigurationRequestDto = { domain: ConfigurationDomain.CARPOOL, @@ -50,16 +49,10 @@ describe('Set Configuration Service', () => { ); it('should set an existing configuration item', async () => { jest.spyOn(mockConfigurationRepository, 'set'); - ConfigurationEntity.create = jest.fn().mockReturnValue({ - id: '047a6ecf-23d4-4d3e-877c-3225d560a8da', - }); await setConfigurationService.execute(setConfigurationCommand); expect(mockConfigurationRepository.set).toHaveBeenCalledTimes(1); }); it('should throw an error if something bad happens on configuration item update', async () => { - ConfigurationEntity.create = jest.fn().mockReturnValue({ - id: '047a6ecf-23d4-4d3e-877c-3225d560a8da', - }); await expect( setConfigurationService.execute(setConfigurationCommand), ).rejects.toBeInstanceOf(Error); diff --git a/src/modules/configuration/tests/unit/infrastructure/configuration.repository.spec.ts b/src/modules/configuration/tests/unit/infrastructure/configuration.repository.spec.ts deleted file mode 100644 index a90589a..0000000 --- a/src/modules/configuration/tests/unit/infrastructure/configuration.repository.spec.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { NotFoundException } from '@mobicoop/ddd-library'; -import { ConfigurationMapper } from '@modules/configuration/configuration.mapper'; -import { ConfigurationEntity } from '@modules/configuration/core/domain/configuration.entity'; -import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types'; -import { ConfigurationRepository } from '@modules/configuration/infrastructure/configuration.repository'; -import { Test, TestingModule } from '@nestjs/testing'; -import { getRedisToken } from '@songkeys/nestjs-redis'; - -const mockRedis = { - get: jest - .fn() - .mockImplementationOnce(() => '1') - .mockImplementation(() => null), - set: jest.fn().mockImplementation(), -}; - -const mockConfigurationMapper = { - toDomain: jest.fn().mockImplementation( - () => - new ConfigurationEntity({ - id: '001199d4-7187-4e83-a044-12159cba2e33', - props: { - identifier: { - domain: ConfigurationDomain.CARPOOL, - key: 'seatsProposed', - }, - value: '1', - }, - createdAt: new Date('2023-10-23'), - updatedAt: new Date('2023-10-23'), - }), - ), -}; - -describe('Configuration Repository', () => { - let configurationRepository: ConfigurationRepository; - - beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - { - provide: getRedisToken('default'), - useValue: mockRedis, - }, - { - provide: ConfigurationMapper, - useValue: mockConfigurationMapper, - }, - ConfigurationRepository, - ], - }).compile(); - - configurationRepository = module.get( - ConfigurationRepository, - ); - }); - - it('should be defined', () => { - expect(configurationRepository).toBeDefined(); - }); - - describe('interact', () => { - it('should get a value', async () => { - expect( - ( - await configurationRepository.get({ - domain: ConfigurationDomain.CARPOOL, - key: 'seatsProposed', - }) - ).getProps().value, - ).toBe('1'); - }); - it('should throw if configuration is not found', async () => { - await expect( - configurationRepository.get({ - domain: ConfigurationDomain.CARPOOL, - key: 'seatsProposed', - }), - ).rejects.toBeInstanceOf(NotFoundException); - }); - it('should set a value', async () => { - expect( - await configurationRepository.set( - { - domain: ConfigurationDomain.CARPOOL, - key: 'seatsProposed', - }, - '3', - ), - ).toBeUndefined(); - }); - }); -}); diff --git a/src/modules/configuration/tests/unit/interface/get-configuration.grpc.controller.spec.ts b/src/modules/configuration/tests/unit/interface/get-configuration.grpc.controller.spec.ts index 97b7d36..e5d4dc1 100644 --- a/src/modules/configuration/tests/unit/interface/get-configuration.grpc.controller.spec.ts +++ b/src/modules/configuration/tests/unit/interface/get-configuration.grpc.controller.spec.ts @@ -1,7 +1,6 @@ -import { NotFoundException } from '@mobicoop/ddd-library'; -import { RpcExceptionCode } from '@mobicoop/ddd-library'; +import { ConfigurationDomain } from '@mobicoop/configuration-module'; +import { NotFoundException, RpcExceptionCode } from '@mobicoop/ddd-library'; import { ConfigurationMapper } from '@modules/configuration/configuration.mapper'; -import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types'; import { GetConfigurationGrpcController } from '@modules/configuration/interface/grpc-controllers/get-configuration.grpc.controller'; import { QueryBus } from '@nestjs/cqrs'; import { RpcException } from '@nestjs/microservices'; diff --git a/src/modules/configuration/tests/unit/interface/set-configuration.grpc.controller.spec.ts b/src/modules/configuration/tests/unit/interface/set-configuration.grpc.controller.spec.ts index 94e78f0..2ecdad5 100644 --- a/src/modules/configuration/tests/unit/interface/set-configuration.grpc.controller.spec.ts +++ b/src/modules/configuration/tests/unit/interface/set-configuration.grpc.controller.spec.ts @@ -1,5 +1,8 @@ +import { + ConfigurationDomain, + ConfigurationIdentifier, +} from '@mobicoop/configuration-module'; import { RpcExceptionCode } from '@mobicoop/ddd-library'; -import { ConfigurationDomain } from '@modules/configuration/core/domain/configuration.types'; 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 { CommandBus } from '@nestjs/cqrs'; @@ -15,7 +18,10 @@ const setConfigurationRequest: SetConfigurationRequestDto = { const mockCommandBus = { execute: jest .fn() - .mockImplementationOnce(() => '200d61a8-d878-4378-a609-c19ea71633d2') + .mockImplementationOnce(() => ({ + domain: ConfigurationDomain.CARPOOL, + key: 'seatsProposed', + })) .mockImplementationOnce(() => { throw new Error(); }), @@ -50,7 +56,9 @@ describe('Set Configuration Grpc Controller', () => { it('should set a configuration item', async () => { jest.spyOn(mockCommandBus, 'execute'); - await setConfigurationGrpcController.set(setConfigurationRequest); + const configurationIdentifier: ConfigurationIdentifier = + await setConfigurationGrpcController.set(setConfigurationRequest); + expect(configurationIdentifier.key).toBe('seatsProposed'); expect(mockCommandBus.execute).toHaveBeenCalledTimes(1); }); From bd79b03c6799e14836b176ce6618f2da2bff4ac5 Mon Sep 17 00:00:00 2001 From: sbriat Date: Wed, 25 Oct 2023 16:03:31 +0200 Subject: [PATCH 2/2] 2.1.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index bd173ab..1dd1439 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@mobicoop/configuration", - "version": "2.0.0", + "version": "2.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@mobicoop/configuration", - "version": "2.0.0", + "version": "2.1.0", "license": "AGPL", "dependencies": { "@grpc/grpc-js": "^1.9.6", diff --git a/package.json b/package.json index 25ba444..a4cd062 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mobicoop/configuration", - "version": "2.0.0", + "version": "2.1.0", "description": "Mobicoop V3 Configuration Service", "author": "sbriat", "private": true,