From 3f4236f34f06aca828b2291e94c7da1efb67a6c4 Mon Sep 17 00:00:00 2001 From: Sylvain Briat Date: Wed, 22 Nov 2023 16:21:10 +0100 Subject: [PATCH] find all users by ids --- README.md | 12 + package-lock.json | 859 ++++++++++-------- package.json | 49 +- src/app.constants.ts | 6 - src/app.module.ts | 39 +- .../find-users-by-ids.query-handler.ts | 17 + .../find-users-by-ids.query.ts | 10 + .../user/interface/dtos/users.response.dto.ts | 5 + .../dtos/find-users-by-ids.request.dto.ts | 7 + .../find-users-by-ids.grpc.controller.ts | 44 + .../interface/grpc-controllers/user.proto | 14 +- .../find-users-by-ids.query-handler.spec.ts | 82 ++ .../find-users-by-ids.grpc.controller.spec.ts | 95 ++ src/modules/user/user.module.ts | 8 +- 14 files changed, 815 insertions(+), 432 deletions(-) create mode 100644 src/modules/user/core/application/queries/find-users-by-ids/find-users-by-ids.query-handler.ts create mode 100644 src/modules/user/core/application/queries/find-users-by-ids/find-users-by-ids.query.ts create mode 100644 src/modules/user/interface/dtos/users.response.dto.ts create mode 100644 src/modules/user/interface/grpc-controllers/dtos/find-users-by-ids.request.dto.ts create mode 100644 src/modules/user/interface/grpc-controllers/find-users-by-ids.grpc.controller.ts create mode 100644 src/modules/user/tests/unit/core/find-users-by-ids.query-handler.spec.ts create mode 100644 src/modules/user/tests/unit/interface/find-users-by-ids.grpc.controller.spec.ts diff --git a/README.md b/README.md index 20a2200..353b233 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,18 @@ The app exposes the following [gRPC](https://grpc.io/) services : } ``` +- **FindAllByIds** : find all users for the given ids + + ```json + { + "ids": [ + "80126a61-d128-4f96-afdb-92e33c75a3e1", + "80126a61-d128-4f96-afdb-92e33c75a3e2", + "80126a61-d128-4f96-afdb-92e33c75a3e3" + ] + } + ``` + - **Create** : create a user ```json diff --git a/package-lock.json b/package-lock.json index cdbfc18..aa434b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,27 +9,27 @@ "version": "1.4.0", "license": "AGPL", "dependencies": { - "@grpc/grpc-js": "^1.9.6", + "@grpc/grpc-js": "^1.9.11", "@grpc/proto-loader": "^0.7.10", - "@mobicoop/configuration-module": "^3.0.0", - "@mobicoop/ddd-library": "^2.0.0", + "@mobicoop/configuration-module": "^7.3.0", + "@mobicoop/ddd-library": "^2.4.0", "@mobicoop/health-module": "^2.3.1", "@mobicoop/message-broker-module": "^2.1.1", - "@nestjs/cache-manager": "^2.1.0", - "@nestjs/common": "^10.2.7", + "@nestjs/cache-manager": "^2.1.1", + "@nestjs/common": "^10.2.10", "@nestjs/config": "^3.1.1", - "@nestjs/core": "^10.2.7", + "@nestjs/core": "^10.2.10", "@nestjs/cqrs": "^10.2.6", - "@nestjs/event-emitter": "^2.0.2", - "@nestjs/microservices": "^10.2.7", - "@nestjs/platform-express": "^10.2.7", + "@nestjs/event-emitter": "^2.0.3", + "@nestjs/microservices": "^10.2.10", + "@nestjs/platform-express": "^10.2.10", "@nestjs/terminus": "^10.1.1", - "@prisma/client": "^5.4.2", + "@prisma/client": "^5.6.0", "@songkeys/nestjs-redis": "^10.0.0", - "@types/supertest": "^2.0.14", - "@typescript-eslint/eslint-plugin": "^6.8.0", - "@typescript-eslint/parser": "^6.8.0", - "cache-manager": "^5.2.4", + "@types/supertest": "^2.0.16", + "@typescript-eslint/eslint-plugin": "^6.12.0", + "@typescript-eslint/parser": "^6.12.0", + "cache-manager": "^5.3.1", "cache-manager-ioredis-yet": "^1.2.2", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", @@ -37,25 +37,25 @@ "ioredis": "^5.3.2" }, "devDependencies": { - "@nestjs/cli": "^10.1.18", - "@nestjs/schematics": "^10.0.2", - "@nestjs/testing": "^10.2.7", - "@types/jest": "^29.5.6", - "@types/node": "^20.8.6", - "@types/uuid": "^9.0.5", - "eslint": "^8.51.0", + "@nestjs/cli": "^10.2.1", + "@nestjs/schematics": "^10.0.3", + "@nestjs/testing": "^10.2.10", + "@types/jest": "^29.5.10", + "@types/node": "^20.9.4", + "@types/uuid": "^9.0.7", + "eslint": "^8.54.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-prettier": "^5.0.1", "jest": "29.7.0", - "prettier": "^3.0.3", - "prisma": "^5.4.2", + "prettier": "^3.1.0", + "prisma": "^5.6.0", "source-map-support": "^0.5.21", "supertest": "^6.3.3", "ts-jest": "29.1.1", - "ts-loader": "^9.5.0", + "ts-loader": "^9.5.1", "ts-node": "^10.9.1", "tsconfig-paths": "4.2.0", - "typescript": "^5.2.2" + "typescript": "^5.3.2" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -93,9 +93,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.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.8.tgz", + "integrity": "sha512-PTGozYvh1Bin5lB15PwcXa26Ayd17bWGLS3H8Rs0s+04mUDvfNofmweaX1LgumWWy3nCUTDuwHxX10M3G0wE2g==", "dev": true, "dependencies": { "ajv": "8.12.0", @@ -120,12 +120,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.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.8.tgz", + "integrity": "sha512-MBiKZOlR9/YMdflALr7/7w/BGAfo/BGTrlkqsIB6rDWV1dYiCgxI+033HsiNssLS6RQyCFx/e7JA2aBBzu9zEg==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.3", + "@angular-devkit/core": "16.2.8", "jsonc-parser": "3.2.0", "magic-string": "0.30.1", "ora": "5.4.1", @@ -138,13 +138,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.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-16.2.8.tgz", + "integrity": "sha512-EXURJCzWTVYCipiTT4vxQQOrF63asOUDbeOy3OtiSh7EwIUvxm3BPG6hquJqngEnI/N6bA75NJ1fBhU6Hrh7eA==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.3", - "@angular-devkit/schematics": "16.2.3", + "@angular-devkit/core": "16.2.8", + "@angular-devkit/schematics": "16.2.8", "ansi-colors": "4.1.3", "inquirer": "8.2.4", "symbol-observable": "4.0.0", @@ -898,9 +898,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -940,9 +940,9 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "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.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } @@ -1038,9 +1038,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.11", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.11.tgz", + "integrity": "sha512-QDhMfbTROOXUhLHMroow8f3EHiCKUOh6UwxMP5S3EuXMnWMNSVIhatGZRwkpg9OUTYdZPsDUVH3cOAkWhGFUJw==", "dependencies": { "@grpc/proto-loader": "^0.7.8", "@types/node": ">=12.12.47" @@ -1067,11 +1067,11 @@ } }, "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==", "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", "minimatch": "^3.0.5" }, @@ -1092,15 +1092,111 @@ } }, "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==" }, "node_modules/@ioredis/commands": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1563,16 +1659,11 @@ } }, "node_modules/@mobicoop/configuration-module": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@mobicoop/configuration-module/-/configuration-module-3.0.0.tgz", - "integrity": "sha512-oYRpOBRQbrM8SQGsKrXaf3qbKDZwUGrPkvZAcVIT6zQydjbgLv8ev89gKfyZb3ouLfvtFdVQUmkP9GkFz4+xRg==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@mobicoop/configuration-module/-/configuration-module-7.3.0.tgz", + "integrity": "sha512-11Pezs1O+NcOL9aTmMmwsj9BQRqygdk44ubS2SXnZmi9sZUAFwet/lFe77YgKcOAhTeRc5GT9KkebA7r7EmpzQ==", "dependencies": { - "@golevelup/nestjs-rabbitmq": "^4.0.0", - "@nestjs/cqrs": "^10.2.6", "@songkeys/nestjs-redis": "^10.0.0", - "@types/amqplib": "^0.10.2", - "amqplib": "^0.10.3", - "class-validator": "^0.14.0", "ioredis": "^5.3.2" }, "peerDependencies": { @@ -1580,12 +1671,13 @@ } }, "node_modules/@mobicoop/ddd-library": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@mobicoop/ddd-library/-/ddd-library-2.0.0.tgz", - "integrity": "sha512-h7/CXRsmdq9QHecVzTq+tEHfH+4DdBgqOTuIl5P6a9qVVDhMhpWXVEXV0XRFFW4Ig8iZ/hLpQjV15kSPMYTu9A==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@mobicoop/ddd-library/-/ddd-library-2.4.0.tgz", + "integrity": "sha512-GUaDbbr2FdDKsM9nPb5j0cMPNpgdAo5hlpZSDHzErxNCqydtPQnKYmCUdUCwQA8s9UGh1s63Rw1cFnMNjOYbiw==", "dependencies": { "@nestjs/event-emitter": "^2.0.2", "@nestjs/microservices": "^10.2.7", + "@nestjs/swagger": "^7.1.14", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", "uuid": "^9.0.1" @@ -1638,9 +1730,9 @@ } }, "node_modules/@nestjs/cache-manager": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@nestjs/cache-manager/-/cache-manager-2.1.0.tgz", - "integrity": "sha512-9kep3a8Mq5cMuXN/anGhSYc0P48CRBXk5wyJJRBFxhNkCH8AIzZF4CASGVDIEMmm3OjVcEUHojjyJwCODS17Qw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/cache-manager/-/cache-manager-2.1.1.tgz", + "integrity": "sha512-oYfRys4Ng0zp2HTUPNjH7gizf4vvG3PQZZ+3yGemb3xrF+p3JxDSK0cDq9NTjHzD5UmhjiyAftB9GkuL+t3r9g==", "peerDependencies": { "@nestjs/common": "^9.0.0 || ^10.0.0", "@nestjs/core": "^9.0.0 || ^10.0.0", @@ -1650,20 +1742,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.1", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.2.1.tgz", + "integrity": "sha512-CAJAQwmxFZfB3RTvqz/eaXXWpyU+mZ4QSqfBYzjneTsPgF+uyOAW3yQpaLNn9Dfcv39R9UxSuAhayv6yuFd+Jg==", "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.8", + "@angular-devkit/schematics": "16.2.8", + "@angular-devkit/schematics-cli": "16.2.8", "@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.2", + "glob": "10.3.10", "inquirer": "8.2.6", "node-emoji": "1.11.0", "ora": "5.4.1", @@ -1675,14 +1768,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", @@ -1697,79 +1790,78 @@ } } }, - "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==", + "node_modules/@nestjs/cli/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": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" + "balanced-match": "^1.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/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/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "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" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" }, "bin": { - "webpack": "bin/webpack.js" + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@nestjs/cli/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" }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@nestjs/cli/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/@nestjs/cli/node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" } }, "node_modules/@nestjs/common": { - "version": "10.2.7", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.2.7.tgz", - "integrity": "sha512-cUtCRXiUstDmh4bSBhVbq4cI439Gngp4LgLGLBmd5dqFQodfXKnSD441ldYfFiLz4rbUsnoMJz/8ZjuIEI+B7A==", + "version": "10.2.10", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.2.10.tgz", + "integrity": "sha512-fwAk931rjW8CNH2Mgwawq/7HWHH1dxkOLdcgs7U52ddLk8CtHXjejm1cbNahewlSbNhvlOl7y1STLHutE6sUqw==", "dependencies": { "iterare": "1.2.1", "tslib": "2.6.2", @@ -1818,9 +1910,9 @@ } }, "node_modules/@nestjs/core": { - "version": "10.2.7", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.2.7.tgz", - "integrity": "sha512-5GSu53QUUcwX17sNmlJPa1I0wIeAZOKbedyVuQx0ZAwWVa9g0wJBbsNP+R4EJ+j5Dkdzt/8xkiZvnKt8RFRR8g==", + "version": "10.2.10", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.2.10.tgz", + "integrity": "sha512-+ckOI6BPi2ZMHikT9MCG4ctHDc4OnjhoIytrn7f2AYMMXI4bnutJhqyQKc30VDka5x3Wq6QAD57pgSP7y+JjJg==", "hasInstallScript": true, "dependencies": { "@nuxtjs/opencollective": "0.3.2", @@ -1877,9 +1969,9 @@ } }, "node_modules/@nestjs/event-emitter": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@nestjs/event-emitter/-/event-emitter-2.0.2.tgz", - "integrity": "sha512-qxJE+6yKSW/ReBzT1jKES2m3zZh6gmgunDtIvCl66G8i9zZ4TQciwoq01MigqnruTgXjH/AzNPqtr6ZUt207mg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nestjs/event-emitter/-/event-emitter-2.0.3.tgz", + "integrity": "sha512-Pt7KAERrgK0OjvarSI3wfVhwZ8X1iLq1lXuodyRe+Zx3aLLP7fraFUHirASbFkB6KIQ1Zj+gZ1g8a9eu4GfFhw==", "dependencies": { "eventemitter2": "6.4.9" }, @@ -1890,9 +1982,9 @@ } }, "node_modules/@nestjs/mapped-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.2.tgz", - "integrity": "sha512-V0izw6tWs6fTp9+KiiPUbGHWALy563Frn8X6Bm87ANLRuE46iuBMD5acKBDP5lKL/75QFvrzSJT7HkCbB0jTpg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.3.tgz", + "integrity": "sha512-40Zdqg98lqoF0+7ThWIZFStxgzisK6GG22+1ABO4kZiGF/Tu2FE+DYLw+Q9D94vcFWizJ+MSjNN4ns9r6hIGxw==", "peerDependencies": { "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", "class-transformer": "^0.4.0 || ^0.5.0", @@ -1909,9 +2001,9 @@ } }, "node_modules/@nestjs/microservices": { - "version": "10.2.7", - "resolved": "https://registry.npmjs.org/@nestjs/microservices/-/microservices-10.2.7.tgz", - "integrity": "sha512-ggpng1yRuugPufn+OKeHV6Dcw3TWI7lmOvXkyYRwatVHQMvb3MlPpbzsA5PfUlg5DsjPGEWRbkIWN7OFb8OTyw==", + "version": "10.2.10", + "resolved": "https://registry.npmjs.org/@nestjs/microservices/-/microservices-10.2.10.tgz", + "integrity": "sha512-vebXc4lF67grtLr3UXc+rPErH5aCzCez1Y2Oec4k2K4ObhjftNug7L2O9W3XiprHlwPhPXc51VQ9nhKn7IFAxw==", "dependencies": { "iterare": "1.2.1", "tslib": "2.6.2" @@ -1966,9 +2058,9 @@ } }, "node_modules/@nestjs/platform-express": { - "version": "10.2.7", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.2.7.tgz", - "integrity": "sha512-p+kp6aJtkgAdVpUrCVmM6MKtOvjsbt7QofBiZMidjYesZkMeG5gZ1D2SK8XzvQ8VXHJfFgEdY2xcKGB+wJLOYQ==", + "version": "10.2.10", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.2.10.tgz", + "integrity": "sha512-U4KDgtMjH8TqEvt0RzC/POP8ABvL9bYoCScvlGtFSKgVGaMLBKkZ4+jHtbQx6qItYSlBBRUuz/dveMZCObfrkQ==", "dependencies": { "body-parser": "1.20.2", "cors": "2.8.5", @@ -1986,13 +2078,13 @@ } }, "node_modules/@nestjs/schematics": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-10.0.2.tgz", - "integrity": "sha512-DaZZjymYoIfRqC5W62lnYXIIods1PDY6CGc8+IpRwyinzffjKxZ3DF3exu+mdyvllzkXo9DTXkoX4zOPSJHCkw==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-10.0.3.tgz", + "integrity": "sha512-2BRujK0GqGQ7j1Zpz+obVfskDnnOeVKt5aXoSaVngKo8Oczy8uYCY+R547TQB+Kf35epdfFER2pVnQrX3/It5A==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.1.8", - "@angular-devkit/schematics": "16.1.8", + "@angular-devkit/core": "16.2.8", + "@angular-devkit/schematics": "16.2.8", "comment-json": "4.2.3", "jsonc-parser": "3.2.0", "pluralize": "8.0.0" @@ -2001,72 +2093,16 @@ "typescript": ">=4.8.2" } }, - "node_modules/@nestjs/schematics/node_modules/@angular-devkit/core": { - "version": "16.1.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.1.8.tgz", - "integrity": "sha512-dSRD/+bGanArIXkj+kaU1kDFleZeQMzmBiOXX+pK0Ah9/0Yn1VmY3RZh1zcX9vgIQXV+t7UPrTpOjaERMUtVGw==", - "dev": true, - "dependencies": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.0", - "rxjs": "7.8.1", - "source-map": "0.7.4" - }, - "engines": { - "node": "^16.14.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^3.5.2" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@nestjs/schematics/node_modules/@angular-devkit/schematics": { - "version": "16.1.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.1.8.tgz", - "integrity": "sha512-6LyzMdFJs337RTxxkI2U1Ndw0CW5mMX/aXWl8d7cW2odiSrAg8IdlMqpc+AM8+CPfsB0FtS1aWkEZqJLT0jHOg==", - "dev": true, - "dependencies": { - "@angular-devkit/core": "16.1.8", - "jsonc-parser": "3.2.0", - "magic-string": "0.30.0", - "ora": "5.4.1", - "rxjs": "7.8.1" - }, - "engines": { - "node": "^16.14.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@nestjs/schematics/node_modules/magic-string": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", - "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.13" - }, - "engines": { - "node": ">=12" - } - }, "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.16", + "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.1.16.tgz", + "integrity": "sha512-f9KBk/BX9MUKPTj7tQNYJ124wV/jP5W2lwWHLGwe/4qQXixuDOo39zP55HIJ44LE7S04B7BOeUOo9GBJD/vRcw==", "dependencies": { - "@nestjs/mapped-types": "2.0.2", + "@nestjs/mapped-types": "2.0.3", "js-yaml": "4.1.0", "lodash": "4.17.21", "path-to-regexp": "3.2.0", - "swagger-ui-dist": "5.9.0" + "swagger-ui-dist": "5.9.1" }, "peerDependencies": { "@fastify/static": "^6.0.0", @@ -2158,9 +2194,9 @@ } }, "node_modules/@nestjs/testing": { - "version": "10.2.7", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.2.7.tgz", - "integrity": "sha512-d2SIqiJIf/7NSILeNNWSdRvTTpHSouGgisGHwf5PVDC7z4/yXZw/wPO9eJhegnxFlqk6n2LW4QBTmMzbqjAfHA==", + "version": "10.2.10", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.2.10.tgz", + "integrity": "sha512-IVLUnPz/+fkBtPATYfqTIP+phN9yjkXejmj+JyhmcfPJZpxBmD1i9VSMqa4u54l37j0xkGPscQ0IXpbhqMYUKw==", "dev": true, "dependencies": { "tslib": "2.6.2" @@ -2233,6 +2269,16 @@ "npm": ">=5.0.0" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@pkgr/utils": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", @@ -2254,12 +2300,12 @@ } }, "node_modules/@prisma/client": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.4.2.tgz", - "integrity": "sha512-2xsPaz4EaMKj1WS9iW6MlPhmbqtBsXAOeVttSePp8vTFTtvzh2hZbDgswwBdSCgPzmmwF+tLB259QzggvCmJqA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.6.0.tgz", + "integrity": "sha512-mUDefQFa1wWqk4+JhKPYq8BdVoFk9NFMBXUI8jAkBfQTtgx8WPx02U2HB/XbAz3GSUJpeJOKJQtNvaAIDs6sug==", "hasInstallScript": true, "dependencies": { - "@prisma/engines-version": "5.4.1-2.ac9d7041ed77bcc8a8dbd2ab6616b39013829574" + "@prisma/engines-version": "5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee" }, "engines": { "node": ">=16.13" @@ -2274,16 +2320,16 @@ } }, "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==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.6.0.tgz", + "integrity": "sha512-Mt2q+GNJpU2vFn6kif24oRSBQv1KOkYaterQsi0k2/lA+dLvhRX6Lm26gon6PYHwUM8/h8KRgXIUMU0PCLB6bw==", "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==" + "version": "5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee.tgz", + "integrity": "sha512-UoFgbV1awGL/3wXuUK3GDaX2SolqczeeJ5b4FVec9tzeGbSWJboPSbT0psSrmgYAKiKnkOPFSLlH6+b+IyOwAw==" }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", @@ -2522,9 +2568,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.6", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.6.tgz", - "integrity": "sha512-/t9NnzkOpXb4Nfvg17ieHE6EeSjDS2SGSpNYfoLbUAeL/EOueU/RSdOWFpfQTXBEM7BguYW1XQ0EbM+6RlIh6w==", + "version": "29.5.10", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.10.tgz", + "integrity": "sha512-tE4yxKEphEyxj9s4inideLHktW/x6DwesIwWZ9NN1FKf9zbJYsnhBoA9vrHA/IuIOKwPa5PcFBNV4lpMIOEzyQ==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -2537,23 +2583,17 @@ "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==" }, "node_modules/@types/node": { - "version": "20.8.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", - "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", + "version": "20.9.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.4.tgz", + "integrity": "sha512-wmyg8HUhcn6ACjsn8oKYjkN/zUzQeNtMy44weTJSM6p4MMzEOuKbA3OjJ267uPCOW7Xex9dyrNTful8XTQYoDA==", "dependencies": { - "undici-types": "~5.25.1" + "undici-types": "~5.26.4" } }, - "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, "node_modules/@types/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==" + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==" }, "node_modules/@types/stack-utils": { "version": "2.0.1", @@ -2571,17 +2611,17 @@ } }, "node_modules/@types/supertest": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.14.tgz", - "integrity": "sha512-Q900DeeHNFF3ZYYepf/EyJfZDA2JrnWLaSQ0YNV7+2GTo8IlJzauEnDGhya+hauncpBYTYGpVHwGdssJeAQ7eA==", + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.16.tgz", + "integrity": "sha512-6c2ogktZ06tr2ENoZivgm7YnprnhYE4ZoXGMY+oA7IuAf17M8FWvujXZGmxLv8y0PTyts4x5A+erSwVUFA8XSg==", "dependencies": { "@types/superagent": "*" } }, "node_modules/@types/uuid": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.5.tgz", - "integrity": "sha512-xfHdwa1FMJ082prjSJpoEI57GZITiQz10r3vEJCHa2khEFQjKy91aWKz6+zybzssCvXUwE1LQWgWVwZ4nYUvHQ==", + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", + "integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==", "dev": true }, "node_modules/@types/validator": { @@ -2605,15 +2645,15 @@ "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.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", + "integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==", "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.12.0", + "@typescript-eslint/type-utils": "6.12.0", + "@typescript-eslint/utils": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -2639,14 +2679,14 @@ } }, "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.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz", + "integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==", "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.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4" }, "engines": { @@ -2666,12 +2706,12 @@ } }, "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.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", "dependencies": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0" + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2682,12 +2722,12 @@ } }, "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.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz", + "integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==", "dependencies": { - "@typescript-eslint/typescript-estree": "6.8.0", - "@typescript-eslint/utils": "6.8.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/utils": "6.12.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -2708,9 +2748,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.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -2720,12 +2760,12 @@ } }, "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.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", "dependencies": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2746,16 +2786,16 @@ } }, "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.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", "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.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", "semver": "^7.5.4" }, "engines": { @@ -2770,11 +2810,11 @@ } }, "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.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", "dependencies": { - "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/types": "6.12.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2785,6 +2825,11 @@ "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==" + }, "node_modules/@webassemblyjs/ast": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", @@ -3180,9 +3225,9 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/axios": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz", - "integrity": "sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -3644,12 +3689,13 @@ } }, "node_modules/cache-manager": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-5.2.4.tgz", - "integrity": "sha512-gkuCjug16NdGvKm/sydxGVx17uffrSWcEe2xraBtwRCgdYcFxwJAla4OYpASAZT2yhSoxgDiWL9XH6IAChcZJA==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-5.3.1.tgz", + "integrity": "sha512-9HP6nc1ZqyZgcVEpy5XS2ns9MYE6cPEM6InA1wQhR6M7GviJzLH2NTFYnf3NEfRmLE351NCSkDo2VISX8dlG+w==", "dependencies": { "lodash.clonedeep": "^4.5.0", - "lru-cache": "^10.0.1" + "lru-cache": "^10.0.2", + "promise-coalesce": "^1.1.1" } }, "node_modules/cache-manager-ioredis-yet": { @@ -4120,19 +4166,29 @@ } }, "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", "dev": true, "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/create-jest": { @@ -4512,6 +4568,12 @@ "node": ">=12" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -4610,17 +4672,18 @@ } }, "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.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", "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/eslintrc": "^2.1.3", + "@eslint/js": "8.54.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", @@ -5226,16 +5289,44 @@ } } }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "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==", + "dev": true, + "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.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", + "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", "dev": true, "dependencies": { "@babel/code-frame": "^7.16.7", "chalk": "^4.1.2", "chokidar": "^3.5.3", - "cosmiconfig": "^7.0.1", + "cosmiconfig": "^8.2.0", "deepmerge": "^4.2.2", "fs-extra": "^10.0.0", "memfs": "^3.4.1", @@ -6006,6 +6097,24 @@ "node": ">=6" } }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -6779,9 +6888,9 @@ "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" }, "node_modules/lru-cache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", - "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.3.tgz", + "integrity": "sha512-B7gr+F6MkqB3uzINHXNctGieGsRTMwIBgxkp0yq/5BwcuDzD4A8wQpHQW6vDAm1uKSLQghmRdD9sKqf2vJ1cEg==", "engines": { "node": "14 || >=16.14" } @@ -7490,9 +7599,9 @@ } }, "node_modules/prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", + "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -7543,13 +7652,13 @@ } }, "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==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.6.0.tgz", + "integrity": "sha512-EEaccku4ZGshdr2cthYHhf7iyvCcXqwJDvnoQRAJg5ge2Tzpv0e2BaMCp+CbbDUwoVTzwgOap9Zp+d4jFa2O9A==", "devOptional": true, "hasInstallScript": true, "dependencies": { - "@prisma/engines": "5.4.2" + "@prisma/engines": "5.6.0" }, "bin": { "prisma": "build/index.js" @@ -7568,6 +7677,14 @@ "resolved": "https://registry.npmjs.org/promise-breaker/-/promise-breaker-5.0.0.tgz", "integrity": "sha512-mgsWQuG4kJ1dtO6e/QlNDLFtMkMzzecsC69aI5hlLEjGHFNpHrvGhFi4LiK5jg2SMQj74/diH+wZliL9LpGsyA==" }, + "node_modules/promise-coalesce": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/promise-coalesce/-/promise-coalesce-1.1.1.tgz", + "integrity": "sha512-k7+VaIwZc5dRfSF6RELqRY1+LCmcCkrnuNV9HzIpA6iwRHKke+j9yb0LBTTHQ2RRgf6AlMl9TntuTzcgV/BZwg==", + "engines": { + "node": ">=18" + } + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -8346,6 +8463,21 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -8357,6 +8489,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -8456,9 +8601,9 @@ } }, "node_modules/swagger-ui-dist": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.9.0.tgz", - "integrity": "sha512-NUHSYoe5XRTk/Are8jPJ6phzBh3l9l33nEyXosM17QInoV95/jng8+PuSGtbD407QoPf93MH3Bkh773OgesJpA==" + "version": "5.9.1", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.9.1.tgz", + "integrity": "sha512-5zAx+hUwJb9T3EAntc7TqYkV716CMqG6sZpNlAAMOMWkNXRYxGkN8ADIvD55dQZ10LxN90ZM/TQmN7y1gpICnw==" }, "node_modules/symbol-observable": { "version": "4.0.0", @@ -8733,9 +8878,9 @@ } }, "node_modules/ts-loader": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.0.tgz", - "integrity": "sha512-LLlB/pkB4q9mW2yLdFMnK3dEHbrBjeZTYguaaIfusyojBgAGf5kF+O6KcWqiGzWqHk0LBsoolrp4VftEURhybg==", + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", + "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", "dev": true, "dependencies": { "chalk": "^4.1.0", @@ -8886,9 +9031,9 @@ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -8909,14 +9054,14 @@ } }, "node_modules/undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==" + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "engines": { "node": ">= 10.0.0" @@ -9088,7 +9233,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", @@ -9154,7 +9298,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" @@ -9168,7 +9311,6 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "peer": true, "engines": { "node": ">=4.0" } @@ -9285,6 +9427,24 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -9325,15 +9485,6 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/package.json b/package.json index 56c2871..1c2132e 100644 --- a/package.json +++ b/package.json @@ -30,27 +30,26 @@ "migrate:deploy": "npx prisma migrate deploy" }, "dependencies": { - "@grpc/grpc-js": "^1.9.6", + "@grpc/grpc-js": "^1.9.11", "@grpc/proto-loader": "^0.7.10", "@songkeys/nestjs-redis": "^10.0.0", - "@mobicoop/configuration-module": "^3.0.0", - "@mobicoop/ddd-library": "^2.0.0", + "@mobicoop/ddd-library": "^2.4.0", "@mobicoop/health-module": "^2.3.1", "@mobicoop/message-broker-module": "^2.1.1", - "@nestjs/cache-manager": "^2.1.0", - "@nestjs/common": "^10.2.7", + "@nestjs/cache-manager": "^2.1.1", + "@nestjs/common": "^10.2.10", "@nestjs/config": "^3.1.1", - "@nestjs/core": "^10.2.7", + "@nestjs/core": "^10.2.10", "@nestjs/cqrs": "^10.2.6", - "@nestjs/event-emitter": "^2.0.2", - "@nestjs/microservices": "^10.2.7", - "@nestjs/platform-express": "^10.2.7", + "@nestjs/event-emitter": "^2.0.3", + "@nestjs/microservices": "^10.2.10", + "@nestjs/platform-express": "^10.2.10", "@nestjs/terminus": "^10.1.1", - "@prisma/client": "^5.4.2", - "@types/supertest": "^2.0.14", - "@typescript-eslint/eslint-plugin": "^6.8.0", - "@typescript-eslint/parser": "^6.8.0", - "cache-manager": "^5.2.4", + "@prisma/client": "^5.6.0", + "@types/supertest": "^2.0.16", + "@typescript-eslint/eslint-plugin": "^6.12.0", + "@typescript-eslint/parser": "^6.12.0", + "cache-manager": "^5.3.1", "cache-manager-ioredis-yet": "^1.2.2", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", @@ -58,25 +57,25 @@ "ioredis": "^5.3.2" }, "devDependencies": { - "@nestjs/cli": "^10.1.18", - "@nestjs/schematics": "^10.0.2", - "@nestjs/testing": "^10.2.7", - "@types/jest": "^29.5.6", - "@types/node": "^20.8.6", - "@types/uuid": "^9.0.5", - "eslint": "^8.51.0", + "@nestjs/cli": "^10.2.1", + "@nestjs/schematics": "^10.0.3", + "@nestjs/testing": "^10.2.10", + "@types/jest": "^29.5.10", + "@types/node": "^20.9.4", + "@types/uuid": "^9.0.7", + "eslint": "^8.54.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-prettier": "^5.0.1", "jest": "29.7.0", - "prettier": "^3.0.3", - "prisma": "^5.4.2", + "prettier": "^3.1.0", + "prisma": "^5.6.0", "source-map-support": "^0.5.21", "supertest": "^6.3.3", "ts-jest": "29.1.1", - "ts-loader": "^9.5.0", + "ts-loader": "^9.5.1", "ts-node": "^10.9.1", "tsconfig-paths": "4.2.0", - "typescript": "^5.2.2" + "typescript": "^5.3.2" }, "jest": { "moduleFileExtensions": [ diff --git a/src/app.constants.ts b/src/app.constants.ts index bcf3f6a..5c97e5d 100644 --- a/src/app.constants.ts +++ b/src/app.constants.ts @@ -5,12 +5,6 @@ export const SERVICE_NAME = 'user'; export const GRPC_PACKAGE_NAME = 'user'; export const GRPC_SERVICE_NAME = 'UserService'; -// configuration -export const SERVICE_CONFIGURATION_SET_QUEUE = 'user-configuration-set'; -export const SERVICE_CONFIGURATION_DELETE_QUEUE = 'user-configuration-delete'; -export const SERVICE_CONFIGURATION_PROPAGATE_QUEUE = - 'user-configuration-propagate'; - // health export const GRPC_HEALTH_PACKAGE_NAME = 'health'; export const HEALTH_USER_REPOSITORY = 'UserRepository'; diff --git a/src/app.module.ts b/src/app.module.ts index 471305f..33ad5be 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,10 +1,6 @@ import { Module } from '@nestjs/common'; -import { ConfigModule, ConfigService } from '@nestjs/config'; +import { ConfigModule } from '@nestjs/config'; import { UserModule } from './modules/user/user.module'; -import { - ConfigurationModule, - ConfigurationModuleOptions, -} from '@mobicoop/configuration-module'; import { HealthModule, HealthModuleOptions, @@ -18,9 +14,6 @@ import { EventEmitterModule } from '@nestjs/event-emitter'; import { HEALTH_CRITICAL_LOGGING_KEY, HEALTH_USER_REPOSITORY, - SERVICE_CONFIGURATION_DELETE_QUEUE, - SERVICE_CONFIGURATION_PROPAGATE_QUEUE, - SERVICE_CONFIGURATION_SET_QUEUE, SERVICE_NAME, } from './app.constants'; @@ -28,36 +21,6 @@ import { imports: [ ConfigModule.forRoot({ isGlobal: true }), EventEmitterModule.forRoot(), - ConfigurationModule.forRootAsync({ - imports: [ConfigModule], - inject: [ConfigService], - useFactory: async ( - configService: ConfigService, - ): Promise => ({ - domain: configService.get( - 'SERVICE_CONFIGURATION_DOMAIN', - ) as string, - messageBroker: { - uri: configService.get('MESSAGE_BROKER_URI') as string, - exchange: { - name: configService.get( - 'MESSAGE_BROKER_EXCHANGE', - ) as string, - durable: configService.get( - 'MESSAGE_BROKER_EXCHANGE', - ) as boolean, - }, - }, - redis: { - host: configService.get('REDIS_HOST') as string, - password: configService.get('REDIS_PASSWORD'), - port: configService.get('REDIS_PORT') as number, - }, - setConfigurationQueue: SERVICE_CONFIGURATION_SET_QUEUE, - deleteConfigurationQueue: SERVICE_CONFIGURATION_DELETE_QUEUE, - propagateConfigurationQueue: SERVICE_CONFIGURATION_PROPAGATE_QUEUE, - }), - }), HealthModule.forRootAsync({ imports: [UserModule, MessagerModule], inject: [USER_REPOSITORY, MESSAGE_PUBLISHER], diff --git a/src/modules/user/core/application/queries/find-users-by-ids/find-users-by-ids.query-handler.ts b/src/modules/user/core/application/queries/find-users-by-ids/find-users-by-ids.query-handler.ts new file mode 100644 index 0000000..6bf00c9 --- /dev/null +++ b/src/modules/user/core/application/queries/find-users-by-ids/find-users-by-ids.query-handler.ts @@ -0,0 +1,17 @@ +import { IQueryHandler, QueryHandler } from '@nestjs/cqrs'; +import { Inject } from '@nestjs/common'; +import { USER_REPOSITORY } from '@modules/user/user.di-tokens'; +import { UserRepositoryPort } from '../../ports/user.repository.port'; +import { UserEntity } from '@modules/user/core/domain/user.entity'; +import { FindUsersByIdsQuery } from './find-users-by-ids.query'; + +@QueryHandler(FindUsersByIdsQuery) +export class FindUsersByIdsQueryHandler implements IQueryHandler { + constructor( + @Inject(USER_REPOSITORY) + private readonly userRepository: UserRepositoryPort, + ) {} + async execute(query: FindUsersByIdsQuery): Promise { + return await this.userRepository.findAllByIds(query.ids); + } +} diff --git a/src/modules/user/core/application/queries/find-users-by-ids/find-users-by-ids.query.ts b/src/modules/user/core/application/queries/find-users-by-ids/find-users-by-ids.query.ts new file mode 100644 index 0000000..e833de8 --- /dev/null +++ b/src/modules/user/core/application/queries/find-users-by-ids/find-users-by-ids.query.ts @@ -0,0 +1,10 @@ +import { QueryBase } from '@mobicoop/ddd-library'; + +export class FindUsersByIdsQuery extends QueryBase { + readonly ids: string[]; + + constructor(ids: string[]) { + super(); + this.ids = ids; + } +} diff --git a/src/modules/user/interface/dtos/users.response.dto.ts b/src/modules/user/interface/dtos/users.response.dto.ts new file mode 100644 index 0000000..fcba084 --- /dev/null +++ b/src/modules/user/interface/dtos/users.response.dto.ts @@ -0,0 +1,5 @@ +import { UserResponseDto } from './user.response.dto'; + +export class UsersResponseDto { + readonly users: readonly UserResponseDto[]; +} diff --git a/src/modules/user/interface/grpc-controllers/dtos/find-users-by-ids.request.dto.ts b/src/modules/user/interface/grpc-controllers/dtos/find-users-by-ids.request.dto.ts new file mode 100644 index 0000000..b1fb95d --- /dev/null +++ b/src/modules/user/interface/grpc-controllers/dtos/find-users-by-ids.request.dto.ts @@ -0,0 +1,7 @@ +import { ArrayMinSize, IsArray } from 'class-validator'; + +export class FindUsersByIdsRequestDto { + @IsArray() + @ArrayMinSize(1) + ids: string[]; +} diff --git a/src/modules/user/interface/grpc-controllers/find-users-by-ids.grpc.controller.ts b/src/modules/user/interface/grpc-controllers/find-users-by-ids.grpc.controller.ts new file mode 100644 index 0000000..e6885cd --- /dev/null +++ b/src/modules/user/interface/grpc-controllers/find-users-by-ids.grpc.controller.ts @@ -0,0 +1,44 @@ +import { Controller, UsePipes } from '@nestjs/common'; +import { QueryBus } from '@nestjs/cqrs'; +import { GrpcMethod, RpcException } from '@nestjs/microservices'; +import { RpcExceptionCode } from '@mobicoop/ddd-library'; +import { RpcValidationPipe } from '@mobicoop/ddd-library'; +import { UserMapper } from '@modules/user/user.mapper'; +import { UserEntity } from '@modules/user/core/domain/user.entity'; +import { GRPC_SERVICE_NAME } from '@src/app.constants'; +import { FindUsersByIdsRequestDto } from './dtos/find-users-by-ids.request.dto'; +import { FindUsersByIdsQuery } from '@modules/user/core/application/queries/find-users-by-ids/find-users-by-ids.query'; +import { UsersResponseDto } from '../dtos/users.response.dto'; + +@UsePipes( + new RpcValidationPipe({ + whitelist: false, + forbidUnknownValues: false, + }), +) +@Controller() +export class FindUsersByIdsGrpcController { + constructor( + protected readonly mapper: UserMapper, + private readonly queryBus: QueryBus, + ) {} + + @GrpcMethod(GRPC_SERVICE_NAME, 'FindAllByIds') + async findAllbyIds( + data: FindUsersByIdsRequestDto, + ): Promise { + try { + const users: UserEntity[] = await this.queryBus.execute( + new FindUsersByIdsQuery(data.ids), + ); + return { + users: users.map((user: UserEntity) => this.mapper.toResponse(user)), + }; + } catch (e) { + throw new RpcException({ + code: RpcExceptionCode.UNKNOWN, + message: e.message, + }); + } + } +} diff --git a/src/modules/user/interface/grpc-controllers/user.proto b/src/modules/user/interface/grpc-controllers/user.proto index 075c6e7..cd3c599 100644 --- a/src/modules/user/interface/grpc-controllers/user.proto +++ b/src/modules/user/interface/grpc-controllers/user.proto @@ -4,7 +4,7 @@ package user; service UserService { rpc FindOneById(UserById) returns (User); - rpc FindAll(UserFilter) returns (Users); + rpc FindAllByIds(UsersById) returns (Users); rpc Create(User) returns (UserById); rpc Update(User) returns (UserById); rpc Delete(UserById) returns (Empty); @@ -14,6 +14,10 @@ message UserById { string id = 1; } +message UsersById { + repeated string ids = 1; +} + message User { string id = 1; string firstName = 2; @@ -22,14 +26,8 @@ message User { string phone = 5; } -message UserFilter { - optional int32 page = 1; - optional int32 perPage = 2; -} - message Users { - repeated User data = 1; - int32 total = 2; + repeated User users = 1; } message Empty {} diff --git a/src/modules/user/tests/unit/core/find-users-by-ids.query-handler.spec.ts b/src/modules/user/tests/unit/core/find-users-by-ids.query-handler.spec.ts new file mode 100644 index 0000000..67ed6d2 --- /dev/null +++ b/src/modules/user/tests/unit/core/find-users-by-ids.query-handler.spec.ts @@ -0,0 +1,82 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { UserEntity } from '@modules/user/core/domain/user.entity'; +import { USER_REPOSITORY } from '@modules/user/user.di-tokens'; +import { FindUsersByIdsQueryHandler } from '@modules/user/core/application/queries/find-users-by-ids/find-users-by-ids.query-handler'; +import { FindUsersByIdsQuery } from '@modules/user/core/application/queries/find-users-by-ids/find-users-by-ids.query'; + +const now = new Date('2023-06-21 06:00:00'); +const user1: UserEntity = new UserEntity({ + id: 'c160cf8c-f057-4962-841f-3ad68346df44', + props: { + firstName: 'John', + lastName: 'Doe', + email: 'john.doe@email.com', + phone: '+33611223344', + }, + createdAt: now, + updatedAt: now, +}); +const user2: UserEntity = new UserEntity({ + id: 'c160cf8c-f057-4962-841f-3ad68346df55', + props: { + firstName: 'Jane', + lastName: 'Doe', + email: 'jane.doe@email.com', + phone: '+33611223355', + }, + createdAt: now, + updatedAt: now, +}); +const user3: UserEntity = new UserEntity({ + id: 'c160cf8c-f057-4962-841f-3ad68346df66', + props: { + firstName: 'Jimmy', + lastName: 'Doe', + email: 'jimmy.doe@email.com', + phone: '+33611223366', + }, + createdAt: now, + updatedAt: now, +}); + +const mockUserRepository = { + findAllByIds: jest.fn().mockImplementation(() => [user1, user2, user3]), +}; + +describe('Find Users By Ids Query Handler', () => { + let findUsersByIdsQueryHandler: FindUsersByIdsQueryHandler; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: USER_REPOSITORY, + useValue: mockUserRepository, + }, + FindUsersByIdsQueryHandler, + ], + }).compile(); + + findUsersByIdsQueryHandler = module.get( + FindUsersByIdsQueryHandler, + ); + }); + + it('should be defined', () => { + expect(findUsersByIdsQueryHandler).toBeDefined(); + }); + + describe('execution', () => { + it('should return users', async () => { + const findUsersByIdsQuery = new FindUsersByIdsQuery([ + 'c160cf8c-f057-4962-841f-3ad68346df44', + 'c160cf8c-f057-4962-841f-3ad68346df55', + 'c160cf8c-f057-4962-841f-3ad68346df66', + ]); + const users: UserEntity[] = + await findUsersByIdsQueryHandler.execute(findUsersByIdsQuery); + expect(users).toHaveLength(3); + expect(users[1].getProps().firstName).toBe('Jane'); + }); + }); +}); diff --git a/src/modules/user/tests/unit/interface/find-users-by-ids.grpc.controller.spec.ts b/src/modules/user/tests/unit/interface/find-users-by-ids.grpc.controller.spec.ts new file mode 100644 index 0000000..b695dfd --- /dev/null +++ b/src/modules/user/tests/unit/interface/find-users-by-ids.grpc.controller.spec.ts @@ -0,0 +1,95 @@ +import { RpcExceptionCode } from '@mobicoop/ddd-library'; +import { FindUsersByIdsGrpcController } from '@modules/user/interface/grpc-controllers/find-users-by-ids.grpc.controller'; +import { UserMapper } from '@modules/user/user.mapper'; +import { QueryBus } from '@nestjs/cqrs'; +import { RpcException } from '@nestjs/microservices'; +import { Test, TestingModule } from '@nestjs/testing'; + +const mockQueryBus = { + execute: jest + .fn() + .mockImplementationOnce(() => [ + '6dcf093c-c7db-4dae-8e9c-c715cebf83c7', + '6dcf093c-c7db-4dae-8e9c-c715cebf83c8', + '6dcf093c-c7db-4dae-8e9c-c715cebf83c9', + ]) + .mockImplementationOnce(() => { + throw new Error(); + }), +}; + +const mockUserMapper = { + toResponse: jest.fn().mockImplementationOnce(() => ({ + firstName: 'John', + lastName: 'Doe', + email: 'john.doe@email.com', + phone: '+33611223344', + })), +}; + +describe('Find Users By Ids Grpc Controller', () => { + let findUsersbyIdsGrpcController: FindUsersByIdsGrpcController; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: QueryBus, + useValue: mockQueryBus, + }, + { + provide: UserMapper, + useValue: mockUserMapper, + }, + FindUsersByIdsGrpcController, + ], + }).compile(); + + findUsersbyIdsGrpcController = module.get( + FindUsersByIdsGrpcController, + ); + }); + + afterEach(async () => { + jest.clearAllMocks(); + }); + + it('should be defined', () => { + expect(findUsersbyIdsGrpcController).toBeDefined(); + }); + + it('should return users', async () => { + jest.spyOn(mockQueryBus, 'execute'); + jest.spyOn(mockUserMapper, 'toResponse'); + const response = await findUsersbyIdsGrpcController.findAllbyIds({ + ids: [ + '6dcf093c-c7db-4dae-8e9c-c715cebf83c7', + '6dcf093c-c7db-4dae-8e9c-c715cebf83c8', + '6dcf093c-c7db-4dae-8e9c-c715cebf83c9', + ], + }); + expect(response.users).toHaveLength(3); + expect(mockQueryBus.execute).toHaveBeenCalledTimes(1); + expect(mockUserMapper.toResponse).toHaveBeenCalledTimes(3); + }); + + it('should throw a generic RpcException', async () => { + jest.spyOn(mockQueryBus, 'execute'); + jest.spyOn(mockUserMapper, 'toResponse'); + expect.assertions(4); + try { + await findUsersbyIdsGrpcController.findAllbyIds({ + ids: [ + '6dcf093c-c7db-4dae-8e9c-c715cebf83c7', + '6dcf093c-c7db-4dae-8e9c-c715cebf83c8', + '6dcf093c-c7db-4dae-8e9c-c715cebf83c9', + ], + }); + } catch (e: any) { + expect(e).toBeInstanceOf(RpcException); + expect(e.error.code).toBe(RpcExceptionCode.UNKNOWN); + } + expect(mockQueryBus.execute).toHaveBeenCalledTimes(1); + expect(mockUserMapper.toResponse).toHaveBeenCalledTimes(0); + }); +}); diff --git a/src/modules/user/user.module.ts b/src/modules/user/user.module.ts index 62d71c7..62faa9f 100644 --- a/src/modules/user/user.module.ts +++ b/src/modules/user/user.module.ts @@ -20,6 +20,8 @@ import { PublishMessageWhenUserIsCreatedDomainEventHandler } from './core/applic import { PublishMessageWhenUserIsUpdatedDomainEventHandler } from './core/application/event-handlers/publish-message-when-user-is-updated.domain-event-handler'; import { PublishMessageWhenUserIsDeletedDomainEventHandler } from './core/application/event-handlers/publish-message-when-user-is-deleted.domain-event-handler'; import { RedisClientOptions } from '@songkeys/nestjs-redis'; +import { FindUsersByIdsGrpcController } from './interface/grpc-controllers/find-users-by-ids.grpc.controller'; +import { FindUsersByIdsQueryHandler } from './core/application/queries/find-users-by-ids/find-users-by-ids.query-handler'; const imports = [ CqrsModule, @@ -42,6 +44,7 @@ const grpcControllers = [ UpdateUserGrpcController, DeleteUserGrpcController, FindUserByIdGrpcController, + FindUsersByIdsGrpcController, ]; const eventHandlers: Provider[] = [ @@ -56,7 +59,10 @@ const commandHandlers: Provider[] = [ DeleteUserService, ]; -const queryHandlers: Provider[] = [FindUserByIdQueryHandler]; +const queryHandlers: Provider[] = [ + FindUserByIdQueryHandler, + FindUsersByIdsQueryHandler, +]; const mappers: Provider[] = [UserMapper];