From 263133ec302d12073f9b70a7bd45c40f27fce80f Mon Sep 17 00:00:00 2001 From: Sylvain Briat Date: Wed, 22 Nov 2023 17:19:53 +0100 Subject: [PATCH 1/2] find all ads by ids --- README.md | 12 + package-lock.json | 314 +++++++++--------- package.json | 42 +-- src/modules/ad/ad.module.ts | 13 +- .../find-ads-by-ids.query-handler.ts | 20 ++ .../find-ads-by-ids/find-ads-by-ids.query.ts | 10 + .../ad/interface/dtos/ads.response.dto.ts | 5 + .../ad/interface/grpc-controllers/ad.proto | 14 +- .../dtos/find-ads-by-ids.request.dto.ts | 7 + .../find-ads-by-ids.grpc.controller.ts | 42 +++ .../find-ads-by-ids.query-handler.spec.ts | 105 ++++++ .../find-ads-by-ids.grpc.controller.spec.ts | 132 ++++++++ 12 files changed, 535 insertions(+), 181 deletions(-) create mode 100644 src/modules/ad/core/application/queries/find-ads-by-ids/find-ads-by-ids.query-handler.ts create mode 100644 src/modules/ad/core/application/queries/find-ads-by-ids/find-ads-by-ids.query.ts create mode 100644 src/modules/ad/interface/dtos/ads.response.dto.ts create mode 100644 src/modules/ad/interface/grpc-controllers/dtos/find-ads-by-ids.request.dto.ts create mode 100644 src/modules/ad/interface/grpc-controllers/find-ads-by-ids.grpc.controller.ts create mode 100644 src/modules/ad/tests/unit/core/find-ads-by-ids.query-handler.spec.ts create mode 100644 src/modules/ad/tests/unit/interface/find-ads-by-ids.grpc.controller.spec.ts diff --git a/README.md b/README.md index 17bd0cb..f3caab1 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,18 @@ The app exposes the following [gRPC](https://grpc.io/) services : } ``` +- **FindAllByIds** : find all ads for the given ids + + ```json + { + "ids": [ + "80126a61-d128-4f96-afdb-92e33c75a3e1", + "80126a61-d128-4f96-afdb-92e33c75a3e2", + "80126a61-d128-4f96-afdb-92e33c75a3e3" + ] + } + ``` + - **Create** : create an ad Punctual driver ad : diff --git a/package-lock.json b/package-lock.json index 9b1d3e7..f387b75 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,20 +9,20 @@ "version": "2.2.5", "license": "AGPL", "dependencies": { - "@grpc/grpc-js": "^1.9.9", + "@grpc/grpc-js": "^1.9.11", "@grpc/proto-loader": "^0.7.10", - "@mobicoop/ddd-library": "^2.1.1", + "@mobicoop/ddd-library": "^2.4.0", "@mobicoop/health-module": "^2.3.1", "@mobicoop/message-broker-module": "^2.1.1", - "@nestjs/common": "^10.2.7", + "@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.5.2", + "@prisma/client": "^5.6.0", "@songkeys/nestjs-redis": "^10.0.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", @@ -36,28 +36,28 @@ "devDependencies": { "@nestjs/cli": "^10.2.1", "@nestjs/schematics": "^10.0.3", - "@nestjs/testing": "^10.2.7", - "@types/express": "^4.17.20", - "@types/jest": "29.5.7", - "@types/node": "20.8.10", - "@types/supertest": "^2.0.15", - "@types/uuid": "^9.0.6", - "@typescript-eslint/eslint-plugin": "^6.9.1", - "@typescript-eslint/parser": "^6.9.1", + "@nestjs/testing": "^10.2.10", + "@types/express": "^4.17.21", + "@types/jest": "29.5.10", + "@types/node": "20.9.4", + "@types/supertest": "^2.0.16", + "@types/uuid": "^9.0.7", + "@typescript-eslint/eslint-plugin": "^6.12.0", + "@typescript-eslint/parser": "^6.12.0", "dotenv-cli": "^7.3.0", - "eslint": "^8.52.0", + "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.5.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": { @@ -894,9 +894,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==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -939,9 +939,9 @@ "dev": true }, "node_modules/@eslint/js": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", - "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1038,9 +1038,9 @@ ] }, "node_modules/@grpc/grpc-js": { - "version": "1.9.9", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.9.tgz", - "integrity": "sha512-vQ1qwi/Kiyprt+uhb1+rHMpyk4CVRMTGNUGGPRGS7pLNfWkdCHrGEnT6T3/JyC2VZgoOX/X1KwdoU0WYQAeYcQ==", + "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" @@ -1662,12 +1662,13 @@ } }, "node_modules/@mobicoop/ddd-library": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@mobicoop/ddd-library/-/ddd-library-2.1.1.tgz", - "integrity": "sha512-Up9d0Ad6aM8Eoc7u3cTMMhQ6uP16thvXLy7h8OL3pfM4QPUNdSygxFjJhwg+wUyjGRH1bsb3xuWp8+GsOVI7+g==", + "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" @@ -1823,10 +1824,23 @@ "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", @@ -1875,9 +1889,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", @@ -1934,9 +1948,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" }, @@ -1947,9 +1961,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", @@ -1966,9 +1980,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" @@ -2023,9 +2037,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", @@ -2059,15 +2073,15 @@ } }, "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", @@ -2159,9 +2173,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" @@ -2268,12 +2282,12 @@ } }, "node_modules/@prisma/client": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.5.2.tgz", - "integrity": "sha512-54XkqR8M+fxbzYqe+bIXimYnkkcGqgOh0dn0yWtIk6CQT4IUCAvNFNcQZwk2KqaLU+/1PHTSWrcHtx4XjluR5w==", + "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.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a" + "@prisma/engines-version": "5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee" }, "engines": { "node": ">=16.13" @@ -2288,16 +2302,16 @@ } }, "node_modules/@prisma/engines": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.5.2.tgz", - "integrity": "sha512-Be5hoNF8k+lkB3uEMiCHbhbfF6aj1GnrTBnn5iYFT7GEr3TsOEp1soviEcBR0tYCgHbxjcIxJMhdbvxALJhAqg==", + "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.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a.tgz", - "integrity": "sha512-O+qHFnZvAyOFk1tUco2/VdiqS0ym42a3+6CYLScllmnpbyiTplgyLt2rK/B9BTjYkSHjrgMhkG47S0oqzdIckA==" + "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", @@ -2554,9 +2568,9 @@ "dev": true }, "node_modules/@types/express": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.20.tgz", - "integrity": "sha512-rOaqlkgEvOW495xErXMsmyX3WKBInbhG5eqojXYi3cGUaLoRDlXa5d52fkfWZT963AZ3v2eZ4MbKE6WpDAGVsw==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", "dev": true, "dependencies": { "@types/body-parser": "*", @@ -2617,9 +2631,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.7", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.7.tgz", - "integrity": "sha512-HLyetab6KVPSiF+7pFcUyMeLsx25LDNDemw9mGsJBkai/oouwrjTycocSDYopMEwFhN2Y4s9oPyOCZNofgSt2g==", + "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", @@ -2639,9 +2653,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", - "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", + "version": "20.9.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.4.tgz", + "integrity": "sha512-wmyg8HUhcn6ACjsn8oKYjkN/zUzQeNtMy44weTJSM6p4MMzEOuKbA3OjJ267uPCOW7Xex9dyrNTful8XTQYoDA==", "dependencies": { "undici-types": "~5.26.4" } @@ -2659,9 +2673,9 @@ "dev": true }, "node_modules/@types/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, "node_modules/@types/send": { @@ -2702,18 +2716,18 @@ } }, "node_modules/@types/supertest": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.15.tgz", - "integrity": "sha512-jUCZZ/TMcpGzoSaed9Gjr8HCf3HehExdibyw3OHHEL1als1KmyzcOZZH4MjbObI8TkWsEr7bc7gsW0WTDni+qQ==", + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.16.tgz", + "integrity": "sha512-6c2ogktZ06tr2ENoZivgm7YnprnhYE4ZoXGMY+oA7IuAf17M8FWvujXZGmxLv8y0PTyts4x5A+erSwVUFA8XSg==", "dev": true, "dependencies": { "@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==", + "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": { @@ -2737,16 +2751,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.1.tgz", - "integrity": "sha512-w0tiiRc9I4S5XSXXrMHOWgHgxbrBn1Ro+PmiYhSg2ZVdxrAJtQgzU5o2m1BfP6UOn7Vxcc6152vFjQfmZR4xEg==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", + "integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.9.1", - "@typescript-eslint/type-utils": "6.9.1", - "@typescript-eslint/utils": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1", + "@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", @@ -2772,15 +2786,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.1.tgz", - "integrity": "sha512-C7AK2wn43GSaCUZ9do6Ksgi2g3mwFkMO3Cis96kzmgudoVaKyt62yNzJOktP0HDLb/iO2O0n2lBOzJgr6Q/cyg==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz", + "integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.9.1", - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/typescript-estree": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1", + "@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": { @@ -2800,13 +2814,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", - "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1" + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2817,13 +2831,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.1.tgz", - "integrity": "sha512-eh2oHaUKCK58qIeYp19F5V5TbpM52680sB4zNSz29VBQPTWIlE/hCj5P5B1AChxECe/fmZlspAWFuRniep1Skg==", + "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==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.9.1", - "@typescript-eslint/utils": "6.9.1", + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/utils": "6.12.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -2844,9 +2858,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", - "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", + "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==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2857,13 +2871,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", - "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1", + "@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", @@ -2884,17 +2898,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.1.tgz", - "integrity": "sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", "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.9.1", - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/typescript-estree": "6.9.1", + "@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": { @@ -2909,12 +2923,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", - "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/types": "6.12.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -4783,15 +4797,15 @@ } }, "node_modules/eslint": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", - "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.52.0", + "@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", @@ -7879,9 +7893,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" @@ -7932,13 +7946,13 @@ } }, "node_modules/prisma": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.5.2.tgz", - "integrity": "sha512-WQtG6fevOL053yoPl6dbHV+IWgKo25IRN4/pwAGqcWmg7CrtoCzvbDbN9fXUc7QS2KK0LimHIqLsaCOX/vHl8w==", + "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.5.2" + "@prisma/engines": "5.6.0" }, "bin": { "prisma": "build/index.js" @@ -8929,9 +8943,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", @@ -9223,9 +9237,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", @@ -9377,9 +9391,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==", "dev": true, "bin": { "tsc": "bin/tsc", diff --git a/package.json b/package.json index 4dc108f..c6615e0 100644 --- a/package.json +++ b/package.json @@ -30,21 +30,21 @@ "migrate:deploy": "npx prisma migrate deploy" }, "dependencies": { - "@grpc/grpc-js": "^1.9.9", + "@grpc/grpc-js": "^1.9.11", "@grpc/proto-loader": "^0.7.10", "@songkeys/nestjs-redis": "^10.0.0", - "@mobicoop/ddd-library": "^2.1.1", + "@mobicoop/ddd-library": "^2.4.0", "@mobicoop/health-module": "^2.3.1", "@mobicoop/message-broker-module": "^2.1.1", - "@nestjs/common": "^10.2.7", + "@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.5.2", + "@prisma/client": "^5.6.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", "geo-tz": "^7.0.7", @@ -57,28 +57,28 @@ "devDependencies": { "@nestjs/cli": "^10.2.1", "@nestjs/schematics": "^10.0.3", - "@nestjs/testing": "^10.2.7", - "@types/express": "^4.17.20", - "@types/jest": "29.5.7", - "@types/node": "20.8.10", - "@types/supertest": "^2.0.15", - "@types/uuid": "^9.0.6", - "@typescript-eslint/eslint-plugin": "^6.9.1", - "@typescript-eslint/parser": "^6.9.1", + "@nestjs/testing": "^10.2.10", + "@types/express": "^4.17.21", + "@types/jest": "29.5.10", + "@types/node": "20.9.4", + "@types/supertest": "^2.0.16", + "@types/uuid": "^9.0.7", + "@typescript-eslint/eslint-plugin": "^6.12.0", + "@typescript-eslint/parser": "^6.12.0", "dotenv-cli": "^7.3.0", - "eslint": "^8.52.0", + "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.5.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/modules/ad/ad.module.ts b/src/modules/ad/ad.module.ts index b79cd5f..28cad5b 100644 --- a/src/modules/ad/ad.module.ts +++ b/src/modules/ad/ad.module.ts @@ -21,8 +21,14 @@ import { PrismaService } from './infrastructure/prisma.service'; import { MessageBrokerPublisher } from '@mobicoop/message-broker-module'; import { InputDateTimeTransformer } from './infrastructure/input-datetime-transformer'; import { OutputDateTimeTransformer } from './infrastructure/output-datetime-transformer'; +import { FindAdsByIdsGrpcController } from './interface/grpc-controllers/find-ads-by-ids.grpc.controller'; +import { FindAdsByIdsQueryHandler } from './core/application/queries/find-ads-by-ids/find-ads-by-ids.query-handler'; -const grpcControllers = [CreateAdGrpcController, FindAdByIdGrpcController]; +const grpcControllers = [ + CreateAdGrpcController, + FindAdByIdGrpcController, + FindAdsByIdsGrpcController, +]; const eventHandlers: Provider[] = [ PublishMessageWhenAdIsCreatedDomainEventHandler, @@ -30,7 +36,10 @@ const eventHandlers: Provider[] = [ const commandHandlers: Provider[] = [CreateAdService]; -const queryHandlers: Provider[] = [FindAdByIdQueryHandler]; +const queryHandlers: Provider[] = [ + FindAdByIdQueryHandler, + FindAdsByIdsQueryHandler, +]; const mappers: Provider[] = [AdMapper]; diff --git a/src/modules/ad/core/application/queries/find-ads-by-ids/find-ads-by-ids.query-handler.ts b/src/modules/ad/core/application/queries/find-ads-by-ids/find-ads-by-ids.query-handler.ts new file mode 100644 index 0000000..fbeebfc --- /dev/null +++ b/src/modules/ad/core/application/queries/find-ads-by-ids/find-ads-by-ids.query-handler.ts @@ -0,0 +1,20 @@ +import { IQueryHandler, QueryHandler } from '@nestjs/cqrs'; +import { AD_REPOSITORY } from '@modules/ad/ad.di-tokens'; +import { AdRepositoryPort } from '../../ports/ad.repository.port'; +import { Inject } from '@nestjs/common'; +import { AdEntity } from '../../../domain/ad.entity'; +import { FindAdsByIdsQuery } from './find-ads-by-ids.query'; + +@QueryHandler(FindAdsByIdsQuery) +export class FindAdsByIdsQueryHandler implements IQueryHandler { + constructor( + @Inject(AD_REPOSITORY) + private readonly repository: AdRepositoryPort, + ) {} + async execute(query: FindAdsByIdsQuery): Promise { + return await this.repository.findAllByIds(query.ids, { + waypoints: true, + schedule: true, + }); + } +} diff --git a/src/modules/ad/core/application/queries/find-ads-by-ids/find-ads-by-ids.query.ts b/src/modules/ad/core/application/queries/find-ads-by-ids/find-ads-by-ids.query.ts new file mode 100644 index 0000000..df4337b --- /dev/null +++ b/src/modules/ad/core/application/queries/find-ads-by-ids/find-ads-by-ids.query.ts @@ -0,0 +1,10 @@ +import { QueryBase } from '@mobicoop/ddd-library'; + +export class FindAdsByIdsQuery extends QueryBase { + readonly ids: string[]; + + constructor(ids: string[]) { + super(); + this.ids = ids; + } +} diff --git a/src/modules/ad/interface/dtos/ads.response.dto.ts b/src/modules/ad/interface/dtos/ads.response.dto.ts new file mode 100644 index 0000000..64a9594 --- /dev/null +++ b/src/modules/ad/interface/dtos/ads.response.dto.ts @@ -0,0 +1,5 @@ +import { AdResponseDto } from './ad.response.dto'; + +export class AdsResponseDto { + readonly ads: readonly AdResponseDto[]; +} diff --git a/src/modules/ad/interface/grpc-controllers/ad.proto b/src/modules/ad/interface/grpc-controllers/ad.proto index b241574..ed31d44 100644 --- a/src/modules/ad/interface/grpc-controllers/ad.proto +++ b/src/modules/ad/interface/grpc-controllers/ad.proto @@ -4,7 +4,7 @@ package ad; service AdService { rpc FindOneById(AdById) returns (Ad); - rpc FindAll(AdFilter) returns (Ads); + rpc FindAllByIds(AdsById) returns (Ads); rpc Create(Ad) returns (AdById); rpc Update(Ad) returns (Ad); rpc Delete(AdById) returns (Empty); @@ -14,6 +14,10 @@ message AdById { string id = 1; } +message AdsById { + repeated string ids = 1; +} + message Ad { string id = 1; string userId = 2; @@ -52,14 +56,8 @@ enum Frequency { RECURRENT = 2; } -message AdFilter { - int32 page = 1; - int32 perPage = 2; -} - message Ads { - repeated Ad data = 1; - int32 total = 2; + repeated Ad ads = 1; } message Empty {} diff --git a/src/modules/ad/interface/grpc-controllers/dtos/find-ads-by-ids.request.dto.ts b/src/modules/ad/interface/grpc-controllers/dtos/find-ads-by-ids.request.dto.ts new file mode 100644 index 0000000..732b4bd --- /dev/null +++ b/src/modules/ad/interface/grpc-controllers/dtos/find-ads-by-ids.request.dto.ts @@ -0,0 +1,7 @@ +import { ArrayMinSize, IsArray } from 'class-validator'; + +export class FindAdsByIdsRequestDto { + @IsArray() + @ArrayMinSize(1) + ids: string[]; +} diff --git a/src/modules/ad/interface/grpc-controllers/find-ads-by-ids.grpc.controller.ts b/src/modules/ad/interface/grpc-controllers/find-ads-by-ids.grpc.controller.ts new file mode 100644 index 0000000..14f8c64 --- /dev/null +++ b/src/modules/ad/interface/grpc-controllers/find-ads-by-ids.grpc.controller.ts @@ -0,0 +1,42 @@ +import { Controller, UsePipes } from '@nestjs/common'; +import { QueryBus } from '@nestjs/cqrs'; +import { GrpcMethod, RpcException } from '@nestjs/microservices'; +import { AdEntity } from '@modules/ad/core/domain/ad.entity'; +import { AdMapper } from '@modules/ad/ad.mapper'; +import { RpcExceptionCode } from '@mobicoop/ddd-library'; +import { RpcValidationPipe } from '@mobicoop/ddd-library'; +import { GRPC_SERVICE_NAME } from '@src/app.constants'; +import { FindAdsByIdsRequestDto } from './dtos/find-ads-by-ids.request.dto'; +import { AdsResponseDto } from '../dtos/ads.response.dto'; +import { FindAdsByIdsQuery } from '@modules/ad/core/application/queries/find-ads-by-ids/find-ads-by-ids.query'; + +@UsePipes( + new RpcValidationPipe({ + whitelist: false, + forbidUnknownValues: false, + }), +) +@Controller() +export class FindAdsByIdsGrpcController { + constructor( + protected readonly mapper: AdMapper, + private readonly queryBus: QueryBus, + ) {} + + @GrpcMethod(GRPC_SERVICE_NAME, 'FindAllByIds') + async findAllByIds(data: FindAdsByIdsRequestDto): Promise { + try { + const ads: AdEntity[] = await this.queryBus.execute( + new FindAdsByIdsQuery(data.ids), + ); + return { + ads: ads.map((ad: AdEntity) => this.mapper.toResponse(ad)), + }; + } catch (e) { + throw new RpcException({ + code: RpcExceptionCode.UNKNOWN, + message: e.message, + }); + } + } +} diff --git a/src/modules/ad/tests/unit/core/find-ads-by-ids.query-handler.spec.ts b/src/modules/ad/tests/unit/core/find-ads-by-ids.query-handler.spec.ts new file mode 100644 index 0000000..c9aef33 --- /dev/null +++ b/src/modules/ad/tests/unit/core/find-ads-by-ids.query-handler.spec.ts @@ -0,0 +1,105 @@ +import { AD_REPOSITORY } from '@modules/ad/ad.di-tokens'; +import { AdEntity } from '@modules/ad/core/domain/ad.entity'; +import { CreateAdProps, Frequency } from '@modules/ad/core/domain/ad.types'; +import { WaypointProps } from '@modules/ad/core/domain/value-objects/waypoint.value-object'; +import { Test, TestingModule } from '@nestjs/testing'; +import { FindAdsByIdsQueryHandler } from '@modules/ad/core/application/queries/find-ads-by-ids/find-ads-by-ids.query-handler'; +import { FindAdsByIdsQuery } from '@modules/ad/core/application/queries/find-ads-by-ids/find-ads-by-ids.query'; + +const originWaypointProps: WaypointProps = { + position: 0, + address: { + houseNumber: '5', + street: 'Avenue Foch', + locality: 'Nancy', + postalCode: '54000', + country: 'France', + coordinates: { + lat: 48.689445, + lon: 6.17651, + }, + }, +}; +const destinationWaypointProps: WaypointProps = { + position: 1, + address: { + locality: 'Paris', + postalCode: '75000', + country: 'France', + coordinates: { + lat: 48.8566, + lon: 2.3522, + }, + }, +}; +const baseCreateAdProps = { + userId: 'e8fe64b1-4c33-49e1-9f69-4db48b21df36', + seatsProposed: 3, + seatsRequested: 1, + strict: false, + waypoints: [originWaypointProps, destinationWaypointProps], +}; +const punctualCreateAdProps = { + fromDate: '2023-06-22', + toDate: '2023-06-22', + schedule: [ + { + time: '08:30', + }, + ], + frequency: Frequency.PUNCTUAL, +}; +const punctualPassengerCreateAdProps: CreateAdProps = { + ...baseCreateAdProps, + ...punctualCreateAdProps, + driver: false, + passenger: true, +}; + +const ads: AdEntity[] = [ + AdEntity.create(punctualPassengerCreateAdProps), + AdEntity.create(punctualPassengerCreateAdProps), + AdEntity.create(punctualPassengerCreateAdProps), +]; + +const mockAdRepository = { + findAllByIds: jest.fn().mockImplementation(() => ads), +}; + +describe('Find Ads By Ids Query Handler', () => { + let findAdsByIdsQueryHandler: FindAdsByIdsQueryHandler; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: AD_REPOSITORY, + useValue: mockAdRepository, + }, + FindAdsByIdsQueryHandler, + ], + }).compile(); + + findAdsByIdsQueryHandler = module.get( + FindAdsByIdsQueryHandler, + ); + }); + + it('should be defined', () => { + expect(findAdsByIdsQueryHandler).toBeDefined(); + }); + + describe('execution', () => { + it('should return an ad', async () => { + const findAdsByIdsQuery = new FindAdsByIdsQuery([ + 'dd264806-13b4-4226-9b18-87adf0ad5dd1', + 'dd264806-13b4-4226-9b18-87adf0ad5dd2', + 'dd264806-13b4-4226-9b18-87adf0ad5dd3', + ]); + const ads: AdEntity[] = + await findAdsByIdsQueryHandler.execute(findAdsByIdsQuery); + expect(ads).toHaveLength(3); + expect(ads[1].getProps().fromDate).toBe('2023-06-22'); + }); + }); +}); diff --git a/src/modules/ad/tests/unit/interface/find-ads-by-ids.grpc.controller.spec.ts b/src/modules/ad/tests/unit/interface/find-ads-by-ids.grpc.controller.spec.ts new file mode 100644 index 0000000..ff4bce2 --- /dev/null +++ b/src/modules/ad/tests/unit/interface/find-ads-by-ids.grpc.controller.spec.ts @@ -0,0 +1,132 @@ +import { RpcExceptionCode } from '@mobicoop/ddd-library'; +import { AdMapper } from '@modules/ad/ad.mapper'; +import { Frequency } from '@modules/ad/core/domain/ad.types'; +import { FindAdsByIdsGrpcController } from '@modules/ad/interface/grpc-controllers/find-ads-by-ids.grpc.controller'; +import { QueryBus } from '@nestjs/cqrs'; +import { RpcException } from '@nestjs/microservices'; +import { Test, TestingModule } from '@nestjs/testing'; + +const mockQueryBus = { + execute: jest + .fn() + .mockImplementationOnce(() => [ + '200d61a8-d878-4378-a609-c19ea71633d2', + '200d61a8-d878-4378-a609-c19ea71633d3', + '200d61a8-d878-4378-a609-c19ea71633d4', + ]) + .mockImplementationOnce(() => { + throw new Error(); + }), +}; + +const mockAdMapper = { + toResponse: jest.fn().mockImplementationOnce(() => ({ + userId: '8cc90d1a-4a59-4289-a7d8-078f9db7857f', + driver: true, + passenger: true, + frequency: Frequency.PUNCTUAL, + fromDate: '2023-06-27', + toDate: '2023-06-27', + schedule: { + tue: '07:15', + }, + marginDurations: { + mon: 900, + tue: 900, + wed: 900, + thu: 900, + fri: 900, + sat: 900, + sun: 900, + }, + seatsProposed: 3, + seatsRequested: 1, + waypoints: [ + { + position: 0, + lat: 48.689445, + lon: 6.17651, + houseNumber: '5', + street: 'Avenue Foch', + locality: 'Nancy', + postalCode: '54000', + country: 'France', + }, + { + position: 1, + lat: 48.8566, + lon: 2.3522, + locality: 'Paris', + postalCode: '75000', + country: 'France', + }, + ], + })), +}; + +describe('Find Ads By Ids Grpc Controller', () => { + let findAdsByIdsGrpcController: FindAdsByIdsGrpcController; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: QueryBus, + useValue: mockQueryBus, + }, + { + provide: AdMapper, + useValue: mockAdMapper, + }, + FindAdsByIdsGrpcController, + ], + }).compile(); + + findAdsByIdsGrpcController = module.get( + FindAdsByIdsGrpcController, + ); + }); + + afterEach(async () => { + jest.clearAllMocks(); + }); + + it('should be defined', () => { + expect(findAdsByIdsGrpcController).toBeDefined(); + }); + + it('should return ads', async () => { + jest.spyOn(mockQueryBus, 'execute'); + jest.spyOn(mockAdMapper, 'toResponse'); + const response = await findAdsByIdsGrpcController.findAllByIds({ + ids: [ + '200d61a8-d878-4378-a609-c19ea71633d2', + '200d61a8-d878-4378-a609-c19ea71633d3', + '200d61a8-d878-4378-a609-c19ea71633d4', + ], + }); + expect(response.ads).toHaveLength(3); + expect(mockQueryBus.execute).toHaveBeenCalledTimes(1); + expect(mockAdMapper.toResponse).toHaveBeenCalledTimes(3); + }); + + it('should throw a generic RpcException', async () => { + jest.spyOn(mockQueryBus, 'execute'); + jest.spyOn(mockAdMapper, 'toResponse'); + expect.assertions(4); + try { + await findAdsByIdsGrpcController.findAllByIds({ + ids: [ + '200d61a8-d878-4378-a609-c19ea71633d2', + '200d61a8-d878-4378-a609-c19ea71633d3', + '200d61a8-d878-4378-a609-c19ea71633d4', + ], + }); + } catch (e: any) { + expect(e).toBeInstanceOf(RpcException); + expect(e.error.code).toBe(RpcExceptionCode.UNKNOWN); + } + expect(mockQueryBus.execute).toHaveBeenCalledTimes(1); + expect(mockAdMapper.toResponse).toHaveBeenCalledTimes(0); + }); +}); From 88a975a8a167e2375aeed0ff2fb76fdd09cb5375 Mon Sep 17 00:00:00 2001 From: Sylvain Briat Date: Wed, 22 Nov 2023 17:19:58 +0100 Subject: [PATCH 2/2] 2.3.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 f387b75..64934de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@mobicoop/ad", - "version": "2.2.5", + "version": "2.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@mobicoop/ad", - "version": "2.2.5", + "version": "2.3.0", "license": "AGPL", "dependencies": { "@grpc/grpc-js": "^1.9.11", diff --git a/package.json b/package.json index c6615e0..75a46eb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mobicoop/ad", - "version": "2.2.5", + "version": "2.3.0", "description": "Mobicoop V3 Ad", "author": "sbriat", "private": true,