From d5c2bb396d57b59166df32b41f2bb64e771e84bf Mon Sep 17 00:00:00 2001 From: sbriat Date: Thu, 20 Jul 2023 17:22:31 +0200 Subject: [PATCH 1/9] wip --- .env.dist | 6 +- package-lock.json | 222 ++++--- package.json | 44 +- src/app.constants.ts | 2 - src/app.module.ts | 99 ++- .../adapters/primaries => }/health.proto | 2 +- src/interfaces/message-publisher.ts | 3 - src/main.ts | 4 +- .../secondaries/prisma-repository.abstract.ts | 259 -------- src/modules/database/database.module.ts | 9 - .../database/domain/user-repository.ts | 3 - .../database/exceptions/database.exception.ts | 24 - .../interfaces/collection.interface.ts | 4 - .../interfaces/repository.interface.ts | 18 - .../tests/unit/prisma-repository.spec.ts | 571 ------------------ .../primaries/health-server.controller.ts | 42 -- .../adapters/primaries/health.controller.ts | 36 -- .../adapters/secondaries/message-publisher.ts | 16 - .../prisma.health-indicator.usecase.ts | 25 - src/modules/health/health.module.ts | 28 - .../tests/unit/message-publisher.spec.ts | 36 -- .../prisma.health-indicator.usecase.spec.ts | 58 -- src/modules/messager/messager.di-tokens.ts | 1 + src/modules/messager/messager.module.ts | 36 ++ .../create-user/create-user.command.ts | 16 + .../create-user/create-user.service.ts | 35 ++ .../update-user/update-user.command.ts | 16 + .../update-user/update-user.service.ts | 57 ++ .../application/ports/user.repository.port.ts | 4 + .../events/user-created.domain-events.ts | 16 + .../events/user-updated.domain-events.ts | 16 + src/modules/user/core/domain/user.entity.ts | 46 ++ src/modules/user/core/domain/user.errors.ts | 31 + src/modules/user/core/domain/user.types.ts | 22 + .../infrastructure/prisma.service.ts} | 0 .../user/infrastructure/user.repository.ts | 51 ++ .../create-user.grpc.controller.ts | 41 ++ .../dtos/create-user.request.dto.ts | 19 + .../dtos/update-user.request.dto.ts | 22 + .../update-user.grpc.controller.ts | 56 ++ .../dtos/grpc-controllers/user.proto | 35 ++ .../dtos/user.paginated.response.dto.ts | 6 + .../user/interface/dtos/user.response.dto.ts | 8 + .../adapters/primaries/user.controller.ts | 0 .../adapters/primaries/user.presenter.ts | 0 .../{ => old}/adapters/primaries/user.proto | 0 .../adapters/secondaries/message-publisher.ts | 0 .../adapters/secondaries/users.repository.ts | 0 .../{ => old}/commands/create-user.command.ts | 0 .../{ => old}/commands/delete-user.command.ts | 0 .../{ => old}/commands/update-user.command.ts | 0 .../domain/dtos/create-user.request.ts | 0 .../domain/dtos/find-all-users.request.ts | 0 .../domain/dtos/find-user-by-uuid.request.ts | 0 .../domain/dtos/update-user.request.ts | 0 .../user/{ => old}/domain/entities/user.ts | 0 .../domain/usecases/create-user.usecase.ts | 0 .../domain/usecases/delete-user.usecase.ts | 0 .../domain/usecases/find-all-users.usecase.ts | 0 .../usecases/find-user-by-uuid.usecase.ts | 0 .../domain/usecases/update-user.usecase.ts | 0 .../user/{ => old}/mappers/user.profile.ts | 0 .../{ => old}/queries/find-all-users.query.ts | 0 .../queries/find-user-by-uuid.query.ts | 0 .../tests/unit/find-all-users.usecase.spec.ts | 0 .../unit/find-user-by-uuid.usecase.spec.ts | 0 .../tests/integration/user.repository.spec.ts | 119 ++++ .../integration/users.repository.spec.ts | 174 ------ .../unit/core/create-user.service.spec.ts | 79 +++ .../user/tests/unit/core/user.entity.spec.ts | 17 + .../tests/unit/create-user.usecase.spec.ts | 79 --- .../tests/unit/delete-user.usecase.spec.ts | 93 --- .../infrastructure/user.repository.spec.ts | 36 ++ .../create-user.grpc.controller.spec.ts | 89 +++ .../update-user.grpc.controller.spec.ts | 116 ++++ .../user/tests/unit/message-publisher.spec.ts | 36 -- .../tests/unit/update-user.usecase.spec.ts | 84 --- .../user/tests/unit/user.mapper.spec.ts | 57 ++ src/modules/user/user.di-tokens.ts | 2 + src/modules/user/user.mapper.ts | 64 ++ src/utils/pipes/rpc.validation-pipe.ts | 14 - .../unit/rpc-validation-pipe.usecase.spec.ts | 20 - tsconfig.json | 6 +- 83 files changed, 1332 insertions(+), 1798 deletions(-) delete mode 100644 src/app.constants.ts rename src/{modules/health/adapters/primaries => }/health.proto (93%) delete mode 100644 src/interfaces/message-publisher.ts delete mode 100644 src/modules/database/adapters/secondaries/prisma-repository.abstract.ts delete mode 100644 src/modules/database/database.module.ts delete mode 100644 src/modules/database/domain/user-repository.ts delete mode 100644 src/modules/database/exceptions/database.exception.ts delete mode 100644 src/modules/database/interfaces/collection.interface.ts delete mode 100644 src/modules/database/interfaces/repository.interface.ts delete mode 100644 src/modules/database/tests/unit/prisma-repository.spec.ts delete mode 100644 src/modules/health/adapters/primaries/health-server.controller.ts delete mode 100644 src/modules/health/adapters/primaries/health.controller.ts delete mode 100644 src/modules/health/adapters/secondaries/message-publisher.ts delete mode 100644 src/modules/health/domain/usecases/prisma.health-indicator.usecase.ts delete mode 100644 src/modules/health/health.module.ts delete mode 100644 src/modules/health/tests/unit/message-publisher.spec.ts delete mode 100644 src/modules/health/tests/unit/prisma.health-indicator.usecase.spec.ts create mode 100644 src/modules/messager/messager.di-tokens.ts create mode 100644 src/modules/messager/messager.module.ts create mode 100644 src/modules/user/core/application/commands/create-user/create-user.command.ts create mode 100644 src/modules/user/core/application/commands/create-user/create-user.service.ts create mode 100644 src/modules/user/core/application/commands/update-user/update-user.command.ts create mode 100644 src/modules/user/core/application/commands/update-user/update-user.service.ts create mode 100644 src/modules/user/core/application/ports/user.repository.port.ts create mode 100644 src/modules/user/core/domain/events/user-created.domain-events.ts create mode 100644 src/modules/user/core/domain/events/user-updated.domain-events.ts create mode 100644 src/modules/user/core/domain/user.entity.ts create mode 100644 src/modules/user/core/domain/user.errors.ts create mode 100644 src/modules/user/core/domain/user.types.ts rename src/modules/{database/adapters/secondaries/prisma-service.ts => user/infrastructure/prisma.service.ts} (100%) create mode 100644 src/modules/user/infrastructure/user.repository.ts create mode 100644 src/modules/user/interface/dtos/grpc-controllers/create-user.grpc.controller.ts create mode 100644 src/modules/user/interface/dtos/grpc-controllers/dtos/create-user.request.dto.ts create mode 100644 src/modules/user/interface/dtos/grpc-controllers/dtos/update-user.request.dto.ts create mode 100644 src/modules/user/interface/dtos/grpc-controllers/update-user.grpc.controller.ts create mode 100644 src/modules/user/interface/dtos/grpc-controllers/user.proto create mode 100644 src/modules/user/interface/dtos/user.paginated.response.dto.ts create mode 100644 src/modules/user/interface/dtos/user.response.dto.ts rename src/modules/user/{ => old}/adapters/primaries/user.controller.ts (100%) rename src/modules/user/{ => old}/adapters/primaries/user.presenter.ts (100%) rename src/modules/user/{ => old}/adapters/primaries/user.proto (100%) rename src/modules/user/{ => old}/adapters/secondaries/message-publisher.ts (100%) rename src/modules/user/{ => old}/adapters/secondaries/users.repository.ts (100%) rename src/modules/user/{ => old}/commands/create-user.command.ts (100%) rename src/modules/user/{ => old}/commands/delete-user.command.ts (100%) rename src/modules/user/{ => old}/commands/update-user.command.ts (100%) rename src/modules/user/{ => old}/domain/dtos/create-user.request.ts (100%) rename src/modules/user/{ => old}/domain/dtos/find-all-users.request.ts (100%) rename src/modules/user/{ => old}/domain/dtos/find-user-by-uuid.request.ts (100%) rename src/modules/user/{ => old}/domain/dtos/update-user.request.ts (100%) rename src/modules/user/{ => old}/domain/entities/user.ts (100%) rename src/modules/user/{ => old}/domain/usecases/create-user.usecase.ts (100%) rename src/modules/user/{ => old}/domain/usecases/delete-user.usecase.ts (100%) rename src/modules/user/{ => old}/domain/usecases/find-all-users.usecase.ts (100%) rename src/modules/user/{ => old}/domain/usecases/find-user-by-uuid.usecase.ts (100%) rename src/modules/user/{ => old}/domain/usecases/update-user.usecase.ts (100%) rename src/modules/user/{ => old}/mappers/user.profile.ts (100%) rename src/modules/user/{ => old}/queries/find-all-users.query.ts (100%) rename src/modules/user/{ => old}/queries/find-user-by-uuid.query.ts (100%) rename src/modules/user/{ => old}/tests/unit/find-all-users.usecase.spec.ts (100%) rename src/modules/user/{ => old}/tests/unit/find-user-by-uuid.usecase.spec.ts (100%) create mode 100644 src/modules/user/tests/integration/user.repository.spec.ts delete mode 100644 src/modules/user/tests/integration/users.repository.spec.ts create mode 100644 src/modules/user/tests/unit/core/create-user.service.spec.ts create mode 100644 src/modules/user/tests/unit/core/user.entity.spec.ts delete mode 100644 src/modules/user/tests/unit/create-user.usecase.spec.ts delete mode 100644 src/modules/user/tests/unit/delete-user.usecase.spec.ts create mode 100644 src/modules/user/tests/unit/infrastructure/user.repository.spec.ts create mode 100644 src/modules/user/tests/unit/interface/create-user.grpc.controller.spec.ts create mode 100644 src/modules/user/tests/unit/interface/update-user.grpc.controller.spec.ts delete mode 100644 src/modules/user/tests/unit/message-publisher.spec.ts delete mode 100644 src/modules/user/tests/unit/update-user.usecase.spec.ts create mode 100644 src/modules/user/tests/unit/user.mapper.spec.ts create mode 100644 src/modules/user/user.di-tokens.ts create mode 100644 src/modules/user/user.mapper.ts delete mode 100644 src/utils/pipes/rpc.validation-pipe.ts delete mode 100644 src/utils/tests/unit/rpc-validation-pipe.usecase.spec.ts diff --git a/.env.dist b/.env.dist index 8c1344f..8d4b7f0 100644 --- a/.env.dist +++ b/.env.dist @@ -7,9 +7,9 @@ HEALTH_SERVICE_PORT=6001 # PRISMA DATABASE_URL="postgresql://mobicoop:mobicoop@v3-db:5432/mobicoop?schema=user" -# RABBIT MQ -RMQ_URI=amqp://v3-broker:5672 -RMQ_EXCHANGE=mobicoop +# MESSAGE BROKER +MESSAGE_BROKER_URI=amqp://v3-broker:5672 +MESSAGE_BROKER_EXCHANGE=mobicoop # REDIS REDIS_HOST=v3-redis diff --git a/package-lock.json b/package-lock.json index 68b8edf..604bacb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,14 +9,13 @@ "version": "0.0.1", "license": "AGPL", "dependencies": { - "@automapper/classes": "^8.7.7", - "@automapper/core": "^8.7.7", - "@automapper/nestjs": "^8.7.7", "@grpc/grpc-js": "^1.8.0", "@grpc/proto-loader": "^0.7.4", "@liaoliaots/nestjs-redis": "^9.0.5", - "@mobicoop/configuration-module": "^1.1.0", - "@mobicoop/message-broker-module": "^1.0.5", + "@mobicoop/configuration-module": "^1.2.0", + "@mobicoop/ddd-library": "^0.3.0", + "@mobicoop/health-module": "^2.0.0", + "@mobicoop/message-broker-module": "^1.2.0", "@nestjs/cache-manager": "^1.0.0", "@nestjs/common": "^9.0.0", "@nestjs/config": "^2.2.0", @@ -32,6 +31,7 @@ "cache-manager": "^5.2.1", "cache-manager-ioredis-yet": "^1.1.0", "class-transformer": "^0.5.1", + "class-validator": "^0.14.0", "dotenv-cli": "^6.0.0", "ioredis": "^5.3.0" }, @@ -41,6 +41,7 @@ "@nestjs/testing": "^9.0.0", "@types/jest": "^29.2.5", "@types/node": "^18.11.18", + "@types/uuid": "^9.0.2", "eslint": "^8.0.1", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^4.0.0", @@ -174,39 +175,6 @@ "node": ">=12.0.0" } }, - "node_modules/@automapper/classes": { - "version": "8.7.7", - "resolved": "https://registry.npmjs.org/@automapper/classes/-/classes-8.7.7.tgz", - "integrity": "sha512-FSbvt6QE8XnhKKQZA3kpKLuLrr9x1iW+lNYTrawVLjxQ05zsCGccLxe7moMNrg1wFAVAouQKupFgCGQ7XRjmJw==", - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "@automapper/core": "8.7.7", - "reflect-metadata": "~0.1.13" - } - }, - "node_modules/@automapper/core": { - "version": "8.7.7", - "resolved": "https://registry.npmjs.org/@automapper/core/-/core-8.7.7.tgz", - "integrity": "sha512-YfpDJ/xqwUuC0S+BLNk81ZJfeL7CmjirUX/Gk9eQyx146DKvneBZgeZ9v5rDB51Ti14jTxVHis+5JuT7W/q0TA==", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@automapper/nestjs": { - "version": "8.7.7", - "resolved": "https://registry.npmjs.org/@automapper/nestjs/-/nestjs-8.7.7.tgz", - "integrity": "sha512-9/uYY2cmN7SJjr2QxnfyXsteHrn/RHD+Dg0VMBflzK/e8Bh/KWyOve7+kaFixlUoyHe44aXs2LVaCslqt8wnhQ==", - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "@automapper/core": "8.7.7", - "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0", - "@nestjs/core": "^7.0.0 || ^8.0.0 || ^9.0.0" - } - }, "node_modules/@babel/code-frame": { "version": "7.21.4", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", @@ -259,9 +227,9 @@ } }, "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -311,9 +279,9 @@ } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -1938,12 +1906,12 @@ } }, "node_modules/@mobicoop/configuration-module": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mobicoop/configuration-module/-/configuration-module-1.1.0.tgz", - "integrity": "sha512-4yzCrY8m40XOO3CZnWJC4kHk66sTQCwe5UjKCV/UpNkN9IGUKW+R84J/53aulmGTL95vec7g6tFIwlHJd9BCoA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@mobicoop/configuration-module/-/configuration-module-1.2.0.tgz", + "integrity": "sha512-l0iDae7SgVVmjnCa2MBqAr3Er0yn4E7yiG8e7cs4XtNGUKrC1N0Ju56TEAraEYK9aZAZ36TCs06m1fep+rgwFA==", "dependencies": { + "@golevelup/nestjs-rabbitmq": "^3.6.0", "@liaoliaots/nestjs-redis": "^9.0.5", - "@mobicoop/message-broker-module": "^1.0.4", "@nestjs/cqrs": "^9.0.4", "@types/amqplib": "^0.10.1", "amqplib": "^0.10.3", @@ -1954,10 +1922,43 @@ "@nestjs/common": "^9.4.2" } }, + "node_modules/@mobicoop/ddd-library": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@mobicoop/ddd-library/-/ddd-library-0.3.0.tgz", + "integrity": "sha512-MoUDqlrDmJkumCFSyW9FY2DLbguT4rytFrmBt9tVNCr2Es6nlz4Ml3HVBwJTZrlJFU79XmiUQ5WAO0MHJt+nAg==", + "dependencies": { + "@nestjs/event-emitter": "^1.4.2", + "@nestjs/microservices": "^9.4.0", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.0", + "uuid": "^9.0.0" + }, + "peerDependencies": { + "@nestjs/common": "^9.4.2" + } + }, + "node_modules/@mobicoop/health-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@mobicoop/health-module/-/health-module-2.0.0.tgz", + "integrity": "sha512-r/7zrHJKVRTIiZ50ILy3lEUC/9vi6k0TRcYPMS8zcnUssQg+MPcT5DQS9B9tTB2gkKwcCyxOQlZZIppIybFX3A==", + "dependencies": { + "@grpc/grpc-js": "^1.8.14", + "@grpc/proto-loader": "^0.7.7", + "@mobicoop/ddd-library": "^0.3.0", + "@mobicoop/message-broker-module": "^1.0.5", + "@nestjs/axios": "^3.0.0", + "@nestjs/microservices": "^9.4.2", + "@nestjs/terminus": "^9.2.2", + "axios": "^1.4.0" + }, + "peerDependencies": { + "@nestjs/common": "^9.4.2" + } + }, "node_modules/@mobicoop/message-broker-module": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@mobicoop/message-broker-module/-/message-broker-module-1.0.5.tgz", - "integrity": "sha512-9l2qCUXide2R1GzTmH1Z8CDHV0+zPJVp1OAk0q+PW9M73id6vX3j0uXURhGLQOwe01IhEMKkFs+D6YNPUPqqmw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@mobicoop/message-broker-module/-/message-broker-module-1.2.0.tgz", + "integrity": "sha512-RoSHHK1GyQ/QVDmm3JS/wBfh171oChvyEp6YWmJd12krFLrPVn9MoEvZdyT3I5J31oBiUabMPle5Kdpw+Nrmww==", "dependencies": { "@golevelup/nestjs-rabbitmq": "^3.6.0", "@types/amqplib": "^0.10.1", @@ -1967,6 +1968,17 @@ "@nestjs/common": "^9.4.2" } }, + "node_modules/@nestjs/axios": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.0.0.tgz", + "integrity": "sha512-ULdH03jDWkS5dy9X69XbUVbhC+0pVnrRcj7bIK/ytTZ76w7CgvTZDJqsIyisg3kNOiljRW/4NIjSf3j6YGvl+g==", + "peerDependencies": { + "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", + "axios": "^1.3.1", + "reflect-metadata": "^0.1.12", + "rxjs": "^6.0.0 || ^7.0.0" + } + }, "node_modules/@nestjs/cache-manager": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@nestjs/cache-manager/-/cache-manager-1.0.0.tgz", @@ -2193,6 +2205,19 @@ "rxjs": "^7.2.0" } }, + "node_modules/@nestjs/event-emitter": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@nestjs/event-emitter/-/event-emitter-1.4.2.tgz", + "integrity": "sha512-5mskPMS4KVH6LghC+NynfdmGiMCOOv9CdgVpuWGipLrJECv5KWc7vaW5o/9BYrcqPkN7Ted6CJ+O4AfsTiRlgw==", + "dependencies": { + "eventemitter2": "6.4.9" + }, + "peerDependencies": { + "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0", + "@nestjs/core": "^7.0.0 || ^8.0.0 || ^9.0.0", + "reflect-metadata": "^0.1.12" + } + }, "node_modules/@nestjs/microservices": { "version": "9.4.2", "resolved": "https://registry.npmjs.org/@nestjs/microservices/-/microservices-9.4.2.tgz", @@ -2754,6 +2779,12 @@ "@types/superagent": "*" } }, + "node_modules/@types/uuid": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", + "integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==", + "dev": true + }, "node_modules/@types/validator": { "version": "13.7.17", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.17.tgz", @@ -3340,8 +3371,17 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } }, "node_modules/babel-jest": { "version": "28.1.3", @@ -4043,7 +4083,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -4284,7 +4323,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -4764,6 +4802,11 @@ "node": ">= 0.6" } }, + "node_modules/eventemitter2": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" + }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -5130,6 +5173,25 @@ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "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", @@ -5162,7 +5224,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -5228,20 +5289,6 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -5776,9 +5823,9 @@ } }, "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -7362,9 +7409,9 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -8133,9 +8180,9 @@ } }, "node_modules/protobufjs": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.3.tgz", - "integrity": "sha512-TtpvOqwB5Gdz/PQmOjgsrGH1nHjAQVCN7JG4A6r1sXRWESL5rNMAiRcBQlCAdKxZcAbstExQePYG8xof/JVRgg==", + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz", + "integrity": "sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ==", "hasInstallScript": true, "dependencies": { "@protobufjs/aspromise": "^1.1.2", @@ -8172,6 +8219,11 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -8583,9 +8635,9 @@ "dev": true }, "node_modules/semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -9782,9 +9834,9 @@ } }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", + "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", "engines": { "node": ">=0.10.0" } diff --git a/package.json b/package.json index 956471f..5099135 100644 --- a/package.json +++ b/package.json @@ -17,28 +17,26 @@ "lint:check": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix-dry-run --ignore-path .gitignore", "pretty:check": "./node_modules/.bin/prettier --check .", "pretty": "./node_modules/.bin/prettier --write .", - "test": "npm run migrate:test && dotenv -e .env.test jest", + "test": "npm run test:unit && npm run test:integration", "test:unit": "jest --testPathPattern 'tests/unit/' --verbose", "test:unit:ci": "jest --testPathPattern 'tests/unit/' --coverage", - "test:integration": "npm run migrate:test && dotenv -e .env.test -- jest --testPathPattern 'tests/integration/' --verbose", - "test:integration:ci": "npm run migrate:test:ci && dotenv -e ci/.env.ci -- jest --testPathPattern 'tests/integration/'", + "test:integration": "npm run migrate:test && dotenv -e .env.test -- jest --testPathPattern 'tests/integration/' --verbose --runInBand", + "test:integration:ci": "npm run migrate:test:ci && dotenv -e ci/.env.ci -- jest --testPathPattern 'tests/integration/' --runInBand", "test:cov": "jest --testPathPattern 'tests/unit/' --coverage", "test:e2e": "jest --config ./test/jest-e2e.json", - "generate": "docker exec v3-user-api sh -c 'npx prisma generate'", - "migrate": "docker exec v3-user-api sh -c 'npx prisma migrate dev'", + "migrate": "docker exec v3-auth-api sh -c 'npx prisma migrate dev'", "migrate:test": "dotenv -e .env.test -- npx prisma migrate deploy", "migrate:test:ci": "dotenv -e ci/.env.ci -- npx prisma migrate deploy", "migrate:deploy": "npx prisma migrate deploy" }, "dependencies": { - "@automapper/classes": "^8.7.7", - "@automapper/core": "^8.7.7", - "@automapper/nestjs": "^8.7.7", "@grpc/grpc-js": "^1.8.0", "@grpc/proto-loader": "^0.7.4", "@liaoliaots/nestjs-redis": "^9.0.5", - "@mobicoop/configuration-module": "^1.1.0", - "@mobicoop/message-broker-module": "^1.0.5", + "@mobicoop/configuration-module": "^1.2.0", + "@mobicoop/ddd-library": "^0.3.0", + "@mobicoop/health-module": "^2.0.0", + "@mobicoop/message-broker-module": "^1.2.0", "@nestjs/cache-manager": "^1.0.0", "@nestjs/common": "^9.0.0", "@nestjs/config": "^2.2.0", @@ -54,6 +52,7 @@ "cache-manager": "^5.2.1", "cache-manager-ioredis-yet": "^1.1.0", "class-transformer": "^0.5.1", + "class-validator": "^0.14.0", "dotenv-cli": "^6.0.0", "ioredis": "^5.3.0" }, @@ -63,6 +62,7 @@ "@nestjs/testing": "^9.0.0", "@types/jest": "^29.2.5", "@types/node": "^18.11.18", + "@types/uuid": "^9.0.2", "eslint": "^8.0.1", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^4.0.0", @@ -84,12 +84,12 @@ "ts" ], "modulePathIgnorePatterns": [ - ".controller.ts", ".module.ts", - ".request.ts", - ".presenter.ts", - ".profile.ts", - ".exception.ts", + ".dto.ts", + ".di-tokens.ts", + ".response.ts", + ".port.ts", + "prisma.service.ts", "main.ts" ], "rootDir": "src", @@ -101,15 +101,19 @@ "**/*.(t|j)s" ], "coveragePathIgnorePatterns": [ - ".controller.ts", ".module.ts", - ".request.ts", - ".presenter.ts", - ".profile.ts", - ".exception.ts", + ".dto.ts", + ".di-tokens.ts", + ".response.ts", + ".port.ts", + "prisma.service.ts", "main.ts" ], "coverageDirectory": "../coverage", + "moduleNameMapper": { + "^@modules(.*)": "/modules/$1", + "^@src(.*)": "$1" + }, "testEnvironment": "node" } } diff --git a/src/app.constants.ts b/src/app.constants.ts deleted file mode 100644 index ff96e07..0000000 --- a/src/app.constants.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const MESSAGE_BROKER_PUBLISHER = Symbol(); -export const MESSAGE_PUBLISHER = Symbol(); diff --git a/src/app.module.ts b/src/app.module.ts index 4d481cc..9e7c1bc 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,70 +1,65 @@ -import { classes } from '@automapper/classes'; -import { AutomapperModule } from '@automapper/nestjs'; import { Module } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; -import { HealthModule } from './modules/health/health.module'; import { UserModule } from './modules/user/user.module'; import { ConfigurationModule, ConfigurationModuleOptions, } from '@mobicoop/configuration-module'; import { - MessageBrokerModule, - MessageBrokerModuleOptions, -} from '@mobicoop/message-broker-module'; + HealthModule, + HealthModuleOptions, + HealthRepositoryPort, +} from '@mobicoop/health-module'; +import { MessagerModule } from './modules/messager/messager.module'; +import { USER_REPOSITORY } from './modules/user/user.di-tokens'; +import { MESSAGE_PUBLISHER } from './modules/messager/messager.di-tokens'; +import { MessagePublisherPort } from '@mobicoop/ddd-library'; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true }), - AutomapperModule.forRoot({ strategyInitializer: classes() }), - UserModule, - MessageBrokerModule.forRootAsync( - { - imports: [ConfigModule], - inject: [ConfigService], - useFactory: async ( - configService: ConfigService, - ): Promise => ({ + ConfigurationModule.forRootAsync({ + imports: [ConfigModule], + inject: [ConfigService], + useFactory: async ( + configService: ConfigService, + ): Promise => ({ + domain: configService.get('SERVICE_CONFIGURATION_DOMAIN'), + messageBroker: { uri: configService.get('MESSAGE_BROKER_URI'), exchange: configService.get('MESSAGE_BROKER_EXCHANGE'), - handlers: {}, - }), - }, - false, - ), - ConfigurationModule.forRootAsync( - { - imports: [ConfigModule], - inject: [ConfigService], - useFactory: async ( - configService: ConfigService, - ): Promise => ({ - domain: configService.get('SERVICE_CONFIGURATION_DOMAIN'), - messageBroker: { - uri: configService.get('MESSAGE_BROKER_URI'), - exchange: configService.get('MESSAGE_BROKER_EXCHANGE'), + }, + redis: { + host: configService.get('REDIS_HOST'), + password: configService.get('REDIS_PASSWORD'), + port: configService.get('REDIS_PORT'), + }, + setConfigurationBrokerQueue: 'user-configuration-create-update', + deleteConfigurationQueue: 'user-configuration-delete', + propagateConfigurationQueue: 'user-configuration-propagate', + }), + }), + HealthModule.forRootAsync({ + imports: [UserModule, MessagerModule], + inject: [USER_REPOSITORY, MESSAGE_PUBLISHER], + useFactory: async ( + userRepository: HealthRepositoryPort, + messagePublisher: MessagePublisherPort, + ): Promise => ({ + serviceName: 'user', + criticalLoggingKey: 'logging.user.health.crit', + checkRepositories: [ + { + name: 'UserRepository', + repository: userRepository, }, - redis: { - host: configService.get('REDIS_HOST'), - password: configService.get('REDIS_PASSWORD'), - port: configService.get('REDIS_PORT'), - }, - setConfigurationBrokerRoutingKeys: [ - 'configuration.create', - 'configuration.update', - ], - deleteConfigurationRoutingKey: 'configuration.delete', - propagateConfigurationRoutingKey: 'configuration.propagate', - setConfigurationBrokerQueue: 'user-configuration-create-update', - deleteConfigurationQueue: 'user-configuration-delete', - propagateConfigurationQueue: 'user-configuration-propagate', - }), - }, - true, - ), - HealthModule, + ], + messagePublisher, + }), + }), + UserModule, + MessagerModule, ], - controllers: [], - providers: [], + exports: [UserModule, MessagerModule], }) export class AppModule {} diff --git a/src/modules/health/adapters/primaries/health.proto b/src/health.proto similarity index 93% rename from src/modules/health/adapters/primaries/health.proto rename to src/health.proto index 74e1a4c..556c72b 100644 --- a/src/modules/health/adapters/primaries/health.proto +++ b/src/health.proto @@ -2,7 +2,6 @@ syntax = "proto3"; package health; - service Health { rpc Check(HealthCheckRequest) returns (HealthCheckResponse); } @@ -18,4 +17,5 @@ message HealthCheckResponse { NOT_SERVING = 2; } ServingStatus status = 1; + string message = 2; } diff --git a/src/interfaces/message-publisher.ts b/src/interfaces/message-publisher.ts deleted file mode 100644 index 29ad456..0000000 --- a/src/interfaces/message-publisher.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface IPublishMessage { - publish(routingKey: string, message: string): void; -} diff --git a/src/main.ts b/src/main.ts index 5de5048..4019e8b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -13,8 +13,8 @@ async function bootstrap() { options: { package: ['user', 'health'], protoPath: [ - join(__dirname, 'modules/user/adapters/primaries/user.proto'), - join(__dirname, 'modules/health/adapters/primaries/health.proto'), + join(__dirname, 'modules/user/interface/grpc-controllers/user.proto'), + join(__dirname, 'health.proto'), ], url: process.env.SERVICE_URL + ':' + process.env.SERVICE_PORT, loader: { keepCase: true }, diff --git a/src/modules/database/adapters/secondaries/prisma-repository.abstract.ts b/src/modules/database/adapters/secondaries/prisma-repository.abstract.ts deleted file mode 100644 index c62eaf2..0000000 --- a/src/modules/database/adapters/secondaries/prisma-repository.abstract.ts +++ /dev/null @@ -1,259 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { Prisma } from '@prisma/client'; -import { DatabaseException } from '../../exceptions/database.exception'; -import { ICollection } from '../../interfaces/collection.interface'; -import { IRepository } from '../../interfaces/repository.interface'; -import { PrismaService } from './prisma-service'; - -/** - * Child classes MUST redefined _model property with appropriate model name - */ -@Injectable() -export abstract class PrismaRepository implements IRepository { - protected model: string; - - constructor(protected readonly prisma: PrismaService) {} - - findAll = async ( - page = 1, - perPage = 10, - where?: any, - include?: any, - ): Promise> => { - const [data, total] = await this.prisma.$transaction([ - this.prisma[this.model].findMany({ - where, - include, - skip: (page - 1) * perPage, - take: perPage, - }), - this.prisma[this.model].count({ - where, - }), - ]); - return Promise.resolve({ - data, - total, - }); - }; - - findOneByUuid = async (uuid: string): Promise => { - try { - const entity = await this.prisma[this.model].findUnique({ - where: { uuid }, - }); - - return entity; - } catch (e) { - if (e instanceof Prisma.PrismaClientKnownRequestError) { - throw new DatabaseException( - Prisma.PrismaClientKnownRequestError.name, - e.code, - e.message, - ); - } else { - throw new DatabaseException(); - } - } - }; - - findOne = async (where: any, include?: any): Promise => { - try { - const entity = await this.prisma[this.model].findFirst({ - where: where, - include: include, - }); - - return entity; - } catch (e) { - if (e instanceof Prisma.PrismaClientKnownRequestError) { - throw new DatabaseException( - Prisma.PrismaClientKnownRequestError.name, - e.code, - ); - } else { - throw new DatabaseException(); - } - } - }; - - // TODO : using any is not good, but needed for nested entities - // TODO : Refactor for good clean architecture ? - create = async (entity: Partial | any, include?: any): Promise => { - try { - const res = await this.prisma[this.model].create({ - data: entity, - include: include, - }); - - return res; - } catch (e) { - if (e instanceof Prisma.PrismaClientKnownRequestError) { - throw new DatabaseException( - Prisma.PrismaClientKnownRequestError.name, - e.code, - e.message, - ); - } else { - throw new DatabaseException(); - } - } - }; - - update = async (uuid: string, entity: Partial): Promise => { - try { - const updatedEntity = await this.prisma[this.model].update({ - where: { uuid }, - data: entity, - }); - return updatedEntity; - } catch (e) { - if (e instanceof Prisma.PrismaClientKnownRequestError) { - throw new DatabaseException( - Prisma.PrismaClientKnownRequestError.name, - e.code, - e.message, - ); - } else { - throw new DatabaseException(); - } - } - }; - - updateWhere = async ( - where: any, - entity: Partial | any, - include?: any, - ): Promise => { - try { - const updatedEntity = await this.prisma[this.model].update({ - where: where, - data: entity, - include: include, - }); - - return updatedEntity; - } catch (e) { - if (e instanceof Prisma.PrismaClientKnownRequestError) { - throw new DatabaseException( - Prisma.PrismaClientKnownRequestError.name, - e.code, - e.message, - ); - } else { - throw new DatabaseException(); - } - } - }; - - delete = async (uuid: string): Promise => { - try { - const entity = await this.prisma[this.model].delete({ - where: { uuid }, - }); - - return entity; - } catch (e) { - if (e instanceof Prisma.PrismaClientKnownRequestError) { - throw new DatabaseException( - Prisma.PrismaClientKnownRequestError.name, - e.code, - e.message, - ); - } else { - throw new DatabaseException(); - } - } - }; - - deleteMany = async (where: any): Promise => { - try { - const entity = await this.prisma[this.model].deleteMany({ - where: where, - }); - - return entity; - } catch (e) { - if (e instanceof Prisma.PrismaClientKnownRequestError) { - throw new DatabaseException( - Prisma.PrismaClientKnownRequestError.name, - e.code, - e.message, - ); - } else { - throw new DatabaseException(); - } - } - }; - - findAllByQuery = async ( - include: string[], - where: string[], - ): Promise> => { - const query = `SELECT ${include.join(',')} FROM ${ - this.model - } WHERE ${where.join(' AND ')}`; - const data: T[] = await this.prisma.$queryRawUnsafe(query); - return Promise.resolve({ - data, - total: data.length, - }); - }; - - createWithFields = async (fields: object): Promise => { - try { - const command = `INSERT INTO ${this.model} ("${Object.keys(fields).join( - '","', - )}") VALUES (${Object.values(fields).join(',')})`; - return await this.prisma.$executeRawUnsafe(command); - } catch (e) { - if (e instanceof Prisma.PrismaClientKnownRequestError) { - throw new DatabaseException( - Prisma.PrismaClientKnownRequestError.name, - e.code, - e.message, - ); - } else { - throw new DatabaseException(); - } - } - }; - - updateWithFields = async (uuid: string, entity: object): Promise => { - entity['"updatedAt"'] = `to_timestamp(${Date.now()} / 1000.0)`; - const values = Object.keys(entity).map((key) => `${key} = ${entity[key]}`); - try { - const command = `UPDATE ${this.model} SET ${values.join( - ', ', - )} WHERE uuid = '${uuid}'`; - return await this.prisma.$executeRawUnsafe(command); - } catch (e) { - if (e instanceof Prisma.PrismaClientKnownRequestError) { - throw new DatabaseException( - Prisma.PrismaClientKnownRequestError.name, - e.code, - e.message, - ); - } else { - throw new DatabaseException(); - } - } - }; - - healthCheck = async (): Promise => { - try { - await this.prisma.$queryRaw`SELECT 1`; - return true; - } catch (e) { - if (e instanceof Prisma.PrismaClientKnownRequestError) { - throw new DatabaseException( - Prisma.PrismaClientKnownRequestError.name, - e.code, - e.message, - ); - } else { - throw new DatabaseException(); - } - } - }; -} diff --git a/src/modules/database/database.module.ts b/src/modules/database/database.module.ts deleted file mode 100644 index 82ca949..0000000 --- a/src/modules/database/database.module.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Module } from '@nestjs/common'; -import { PrismaService } from './adapters/secondaries/prisma-service'; -import { UserRepository } from './domain/user-repository'; - -@Module({ - providers: [PrismaService, UserRepository], - exports: [PrismaService, UserRepository], -}) -export class DatabaseModule {} diff --git a/src/modules/database/domain/user-repository.ts b/src/modules/database/domain/user-repository.ts deleted file mode 100644 index 3e88dbb..0000000 --- a/src/modules/database/domain/user-repository.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { PrismaRepository } from '../adapters/secondaries/prisma-repository.abstract'; - -export class UserRepository extends PrismaRepository {} diff --git a/src/modules/database/exceptions/database.exception.ts b/src/modules/database/exceptions/database.exception.ts deleted file mode 100644 index b0782a6..0000000 --- a/src/modules/database/exceptions/database.exception.ts +++ /dev/null @@ -1,24 +0,0 @@ -export class DatabaseException implements Error { - name: string; - message: string; - - constructor( - private _type: string = 'unknown', - private _code: string = '', - message?: string, - ) { - this.name = 'DatabaseException'; - this.message = message ?? 'An error occured with the database.'; - if (this.message.includes('Unique constraint failed')) { - this.message = 'Already exists.'; - } - } - - get type(): string { - return this._type; - } - - get code(): string { - return this._code; - } -} diff --git a/src/modules/database/interfaces/collection.interface.ts b/src/modules/database/interfaces/collection.interface.ts deleted file mode 100644 index 6e9a96d..0000000 --- a/src/modules/database/interfaces/collection.interface.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface ICollection { - data: T[]; - total: number; -} diff --git a/src/modules/database/interfaces/repository.interface.ts b/src/modules/database/interfaces/repository.interface.ts deleted file mode 100644 index 1e23984..0000000 --- a/src/modules/database/interfaces/repository.interface.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { ICollection } from './collection.interface'; - -export interface IRepository { - findAll( - page: number, - perPage: number, - params?: any, - include?: any, - ): Promise>; - findOne(where: any, include?: any): Promise; - findOneByUuid(uuid: string, include?: any): Promise; - create(entity: Partial | any, include?: any): Promise; - update(uuid: string, entity: Partial, include?: any): Promise; - updateWhere(where: any, entity: Partial | any, include?: any): Promise; - delete(uuid: string): Promise; - deleteMany(where: any): Promise; - healthCheck(): Promise; -} diff --git a/src/modules/database/tests/unit/prisma-repository.spec.ts b/src/modules/database/tests/unit/prisma-repository.spec.ts deleted file mode 100644 index eb3bad0..0000000 --- a/src/modules/database/tests/unit/prisma-repository.spec.ts +++ /dev/null @@ -1,571 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { Test, TestingModule } from '@nestjs/testing'; -import { PrismaService } from '../../adapters/secondaries/prisma-service'; -import { PrismaRepository } from '../../adapters/secondaries/prisma-repository.abstract'; -import { DatabaseException } from '../../exceptions/database.exception'; -import { Prisma } from '@prisma/client'; - -class FakeEntity { - uuid?: string; - name: string; -} - -let entityId = 2; -const entityUuid = 'uuid-'; -const entityName = 'name-'; - -const createRandomEntity = (): FakeEntity => { - const entity: FakeEntity = { - uuid: `${entityUuid}${entityId}`, - name: `${entityName}${entityId}`, - }; - - entityId++; - - return entity; -}; - -const fakeEntityToCreate: FakeEntity = { - name: 'test', -}; - -const fakeEntityCreated: FakeEntity = { - ...fakeEntityToCreate, - uuid: 'some-uuid', -}; - -const fakeEntities: FakeEntity[] = []; -Array.from({ length: 10 }).forEach(() => { - fakeEntities.push(createRandomEntity()); -}); - -@Injectable() -class FakePrismaRepository extends PrismaRepository { - protected model = 'fake'; -} - -class FakePrismaService extends PrismaService { - fake: any; -} - -const mockPrismaService = { - $transaction: jest.fn().mockImplementation(async (data: any) => { - const entities = await data[0]; - if (entities.length == 1) { - return Promise.resolve([[fakeEntityCreated], 1]); - } - - return Promise.resolve([fakeEntities, fakeEntities.length]); - }), - // eslint-disable-next-line @typescript-eslint/no-unused-vars - $queryRawUnsafe: jest.fn().mockImplementation((query?: string) => { - return Promise.resolve(fakeEntities); - }), - $executeRawUnsafe: jest - .fn() - .mockResolvedValueOnce(fakeEntityCreated) - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .mockImplementationOnce((fields: object) => { - throw new Prisma.PrismaClientKnownRequestError('unknown request', { - code: 'code', - clientVersion: 'version', - }); - }) - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .mockImplementationOnce((fields: object) => { - throw new Error('an unknown error'); - }) - .mockResolvedValueOnce(fakeEntityCreated) - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .mockImplementationOnce((fields: object) => { - throw new Prisma.PrismaClientKnownRequestError('unknown request', { - code: 'code', - clientVersion: 'version', - }); - }) - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .mockImplementationOnce((fields: object) => { - throw new Error('an unknown error'); - }), - $queryRaw: jest - .fn() - .mockImplementationOnce(() => { - throw new Prisma.PrismaClientKnownRequestError('unknown request', { - code: 'code', - clientVersion: 'version', - }); - }) - .mockImplementationOnce(() => { - return true; - }) - .mockImplementation(() => { - throw new Prisma.PrismaClientKnownRequestError('Database unavailable', { - code: 'code', - clientVersion: 'version', - }); - }), - fake: { - create: jest - .fn() - .mockResolvedValueOnce(fakeEntityCreated) - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .mockImplementationOnce((params?: any) => { - throw new Prisma.PrismaClientKnownRequestError('unknown request', { - code: 'code', - clientVersion: 'version', - }); - }) - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .mockImplementationOnce((params?: any) => { - throw new Error('an unknown error'); - }), - - findMany: jest.fn().mockImplementation((params?: any) => { - if (params?.where?.limit == 1) { - return Promise.resolve([fakeEntityCreated]); - } - - return Promise.resolve(fakeEntities); - }), - count: jest.fn().mockResolvedValue(fakeEntities.length), - - findUnique: jest.fn().mockImplementation(async (params?: any) => { - let entity; - - if (params?.where?.uuid) { - entity = fakeEntities.find( - (entity) => entity.uuid === params?.where?.uuid, - ); - } - - if (!entity && params?.where?.uuid == 'unknown') { - throw new Prisma.PrismaClientKnownRequestError('unknown request', { - code: 'code', - clientVersion: 'version', - }); - } else if (!entity) { - throw new Error('no entity'); - } - - return entity; - }), - - findFirst: jest - .fn() - .mockImplementationOnce((params?: any) => { - if (params?.where?.name) { - return Promise.resolve( - fakeEntities.find((entity) => entity.name === params?.where?.name), - ); - } - }) - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .mockImplementationOnce((params?: any) => { - throw new Prisma.PrismaClientKnownRequestError('unknown request', { - code: 'code', - clientVersion: 'version', - }); - }) - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .mockImplementationOnce((params?: any) => { - throw new Error('an unknown error'); - }), - - update: jest - .fn() - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .mockImplementationOnce((params?: any) => { - throw new Prisma.PrismaClientKnownRequestError('unknown request', { - code: 'code', - clientVersion: 'version', - }); - }) - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .mockImplementationOnce((params?: any) => { - throw new Prisma.PrismaClientKnownRequestError('unknown request', { - code: 'code', - clientVersion: 'version', - }); - }) - .mockImplementationOnce((params: any) => { - const entity = fakeEntities.find( - (entity) => entity.name === params.where.name, - ); - Object.entries(params.data).map(([key, value]) => { - entity[key] = value; - }); - - return Promise.resolve(entity); - }) - .mockImplementation((params: any) => { - const entity = fakeEntities.find( - (entity) => entity.uuid === params.where.uuid, - ); - Object.entries(params.data).map(([key, value]) => { - entity[key] = value; - }); - - return Promise.resolve(entity); - }), - - delete: jest - .fn() - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .mockImplementationOnce((params?: any) => { - throw new Prisma.PrismaClientKnownRequestError('unknown request', { - code: 'code', - clientVersion: 'version', - }); - }) - .mockImplementation((params: any) => { - let found = false; - - fakeEntities.forEach((entity, index) => { - if (entity.uuid === params?.where?.uuid) { - found = true; - fakeEntities.splice(index, 1); - } - }); - - if (!found) { - throw new Error(); - } - }), - - deleteMany: jest - .fn() - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .mockImplementationOnce((params?: any) => { - throw new Prisma.PrismaClientKnownRequestError('unknown request', { - code: 'code', - clientVersion: 'version', - }); - }) - .mockImplementation((params: any) => { - let found = false; - - fakeEntities.forEach((entity, index) => { - if (entity.uuid === params?.where?.uuid) { - found = true; - fakeEntities.splice(index, 1); - } - }); - - if (!found) { - throw new Error(); - } - }), - }, -}; - -describe('PrismaRepository', () => { - let fakeRepository: FakePrismaRepository; - let prisma: FakePrismaService; - - beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - FakePrismaRepository, - { - provide: PrismaService, - useValue: mockPrismaService, - }, - ], - }).compile(); - - fakeRepository = module.get(FakePrismaRepository); - prisma = module.get(PrismaService) as FakePrismaService; - }); - - it('should be defined', () => { - expect(fakeRepository).toBeDefined(); - expect(prisma).toBeDefined(); - }); - - describe('findAll', () => { - it('should return an array of entities', async () => { - jest.spyOn(prisma.fake, 'findMany'); - jest.spyOn(prisma.fake, 'count'); - jest.spyOn(prisma, '$transaction'); - - const entities = await fakeRepository.findAll(); - expect(entities).toStrictEqual({ - data: fakeEntities, - total: fakeEntities.length, - }); - }); - - it('should return an array containing only one entity', async () => { - const entities = await fakeRepository.findAll(1, 10, { limit: 1 }); - - expect(prisma.fake.findMany).toHaveBeenCalledWith({ - skip: 0, - take: 10, - where: { limit: 1 }, - }); - expect(entities).toEqual({ - data: [fakeEntityCreated], - total: 1, - }); - }); - }); - - describe('create', () => { - it('should create an entity', async () => { - jest.spyOn(prisma.fake, 'create'); - - const newEntity = await fakeRepository.create(fakeEntityToCreate); - expect(newEntity).toBe(fakeEntityCreated); - expect(prisma.fake.create).toHaveBeenCalledTimes(1); - }); - - it('should throw a DatabaseException for client error', async () => { - await expect( - fakeRepository.create(fakeEntityToCreate), - ).rejects.toBeInstanceOf(DatabaseException); - }); - - it('should throw a DatabaseException if uuid is not found', async () => { - await expect( - fakeRepository.create(fakeEntityToCreate), - ).rejects.toBeInstanceOf(DatabaseException); - }); - }); - - describe('findOneByUuid', () => { - it('should find an entity by uuid', async () => { - const entity = await fakeRepository.findOneByUuid(fakeEntities[0].uuid); - expect(entity).toBe(fakeEntities[0]); - }); - - it('should throw a DatabaseException for client error', async () => { - await expect( - fakeRepository.findOneByUuid('unknown'), - ).rejects.toBeInstanceOf(DatabaseException); - }); - - it('should throw a DatabaseException if uuid is not found', async () => { - await expect( - fakeRepository.findOneByUuid('wrong-uuid'), - ).rejects.toBeInstanceOf(DatabaseException); - }); - }); - - describe('findOne', () => { - it('should find one entity', async () => { - const entity = await fakeRepository.findOne({ - name: fakeEntities[0].name, - }); - - expect(entity.name).toBe(fakeEntities[0].name); - }); - - it('should throw a DatabaseException for client error', async () => { - await expect( - fakeRepository.findOne({ - name: fakeEntities[0].name, - }), - ).rejects.toBeInstanceOf(DatabaseException); - }); - - it('should throw a DatabaseException for unknown error', async () => { - await expect( - fakeRepository.findOne({ - name: fakeEntities[0].name, - }), - ).rejects.toBeInstanceOf(DatabaseException); - }); - }); - - describe('update', () => { - it('should throw a DatabaseException for client error', async () => { - await expect( - fakeRepository.update('fake-uuid', { name: 'error' }), - ).rejects.toBeInstanceOf(DatabaseException); - await expect( - fakeRepository.updateWhere({ name: 'error' }, { name: 'new error' }), - ).rejects.toBeInstanceOf(DatabaseException); - }); - - it('should update an entity with name', async () => { - const newName = 'new-random-name'; - - await fakeRepository.updateWhere( - { name: fakeEntities[0].name }, - { - name: newName, - }, - ); - expect(fakeEntities[0].name).toBe(newName); - }); - - it('should update an entity with uuid', async () => { - const newName = 'random-name'; - - await fakeRepository.update(fakeEntities[0].uuid, { - name: newName, - }); - expect(fakeEntities[0].name).toBe(newName); - }); - - it("should throw an exception if an entity doesn't exist", async () => { - await expect( - fakeRepository.update('fake-uuid', { name: 'error' }), - ).rejects.toBeInstanceOf(DatabaseException); - await expect( - fakeRepository.updateWhere({ name: 'error' }, { name: 'new error' }), - ).rejects.toBeInstanceOf(DatabaseException); - }); - }); - - describe('delete', () => { - it('should throw a DatabaseException for client error', async () => { - await expect(fakeRepository.delete('fake-uuid')).rejects.toBeInstanceOf( - DatabaseException, - ); - }); - - it('should delete an entity', async () => { - const savedUuid = fakeEntities[0].uuid; - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const res = await fakeRepository.delete(savedUuid); - - const deletedEntity = fakeEntities.find( - (entity) => entity.uuid === savedUuid, - ); - expect(deletedEntity).toBeUndefined(); - }); - - it("should throw an exception if an entity doesn't exist", async () => { - await expect(fakeRepository.delete('fake-uuid')).rejects.toBeInstanceOf( - DatabaseException, - ); - }); - }); - - describe('deleteMany', () => { - it('should throw a DatabaseException for client error', async () => { - await expect( - fakeRepository.deleteMany({ uuid: 'fake-uuid' }), - ).rejects.toBeInstanceOf(DatabaseException); - }); - - it('should delete entities based on their uuid', async () => { - const savedUuid = fakeEntities[0].uuid; - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const res = await fakeRepository.deleteMany({ uuid: savedUuid }); - - const deletedEntity = fakeEntities.find( - (entity) => entity.uuid === savedUuid, - ); - expect(deletedEntity).toBeUndefined(); - }); - - it("should throw an exception if an entity doesn't exist", async () => { - await expect( - fakeRepository.deleteMany({ uuid: 'fake-uuid' }), - ).rejects.toBeInstanceOf(DatabaseException); - }); - }); - - describe('findAllByquery', () => { - it('should return an array of entities', async () => { - const entities = await fakeRepository.findAllByQuery( - ['uuid', 'name'], - ['name is not null'], - ); - expect(entities).toStrictEqual({ - data: fakeEntities, - total: fakeEntities.length, - }); - }); - }); - - describe('createWithFields', () => { - it('should create an entity', async () => { - jest.spyOn(prisma, '$queryRawUnsafe'); - - const newEntity = await fakeRepository.createWithFields({ - uuid: '804319b3-a09b-4491-9f82-7976bfce0aff', - name: 'my-name', - }); - expect(newEntity).toBe(fakeEntityCreated); - expect(prisma.$queryRawUnsafe).toHaveBeenCalledTimes(1); - }); - - it('should throw a DatabaseException for client error', async () => { - await expect( - fakeRepository.createWithFields({ - uuid: '804319b3-a09b-4491-9f82-7976bfce0aff', - name: 'my-name', - }), - ).rejects.toBeInstanceOf(DatabaseException); - }); - - it('should throw a DatabaseException if uuid is not found', async () => { - await expect( - fakeRepository.createWithFields({ - name: 'my-name', - }), - ).rejects.toBeInstanceOf(DatabaseException); - }); - }); - - describe('updateWithFields', () => { - it('should update an entity', async () => { - jest.spyOn(prisma, '$queryRawUnsafe'); - - const updatedEntity = await fakeRepository.updateWithFields( - '804319b3-a09b-4491-9f82-7976bfce0aff', - { - name: 'my-name', - }, - ); - expect(updatedEntity).toBe(fakeEntityCreated); - expect(prisma.$queryRawUnsafe).toHaveBeenCalledTimes(1); - }); - - it('should throw a DatabaseException for client error', async () => { - await expect( - fakeRepository.updateWithFields( - '804319b3-a09b-4491-9f82-7976bfce0aff', - { - name: 'my-name', - }, - ), - ).rejects.toBeInstanceOf(DatabaseException); - }); - - it('should throw a DatabaseException if uuid is not found', async () => { - await expect( - fakeRepository.updateWithFields( - '804319b3-a09b-4491-9f82-7976bfce0aff', - { - name: 'my-name', - }, - ), - ).rejects.toBeInstanceOf(DatabaseException); - }); - }); - - describe('healthCheck', () => { - it('should throw a DatabaseException for client error', async () => { - await expect(fakeRepository.healthCheck()).rejects.toBeInstanceOf( - DatabaseException, - ); - }); - - it('should return a healthy result', async () => { - const res = await fakeRepository.healthCheck(); - expect(res).toBeTruthy(); - }); - - it('should throw an exception if database is not available', async () => { - await expect(fakeRepository.healthCheck()).rejects.toBeInstanceOf( - DatabaseException, - ); - }); - }); -}); diff --git a/src/modules/health/adapters/primaries/health-server.controller.ts b/src/modules/health/adapters/primaries/health-server.controller.ts deleted file mode 100644 index c0d63c8..0000000 --- a/src/modules/health/adapters/primaries/health-server.controller.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { Controller } from '@nestjs/common'; -import { GrpcMethod } from '@nestjs/microservices'; -import { PrismaHealthIndicatorUseCase } from '../../domain/usecases/prisma.health-indicator.usecase'; - -enum ServingStatus { - UNKNOWN = 0, - SERVING = 1, - NOT_SERVING = 2, -} - -interface HealthCheckRequest { - service: string; -} - -interface HealthCheckResponse { - status: ServingStatus; -} - -@Controller() -export class HealthServerController { - constructor( - private readonly prismaHealthIndicatorUseCase: PrismaHealthIndicatorUseCase, - ) {} - - @GrpcMethod('Health', 'Check') - async check( - // eslint-disable-next-line @typescript-eslint/no-unused-vars - data: HealthCheckRequest, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - metadata: any, - ): Promise { - const healthCheck = await this.prismaHealthIndicatorUseCase.isHealthy( - 'prisma', - ); - return { - status: - healthCheck['prisma'].status == 'up' - ? ServingStatus.SERVING - : ServingStatus.NOT_SERVING, - }; - } -} diff --git a/src/modules/health/adapters/primaries/health.controller.ts b/src/modules/health/adapters/primaries/health.controller.ts deleted file mode 100644 index 8946060..0000000 --- a/src/modules/health/adapters/primaries/health.controller.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Controller, Get, Inject } from '@nestjs/common'; -import { - HealthCheckService, - HealthCheck, - HealthCheckResult, -} from '@nestjs/terminus'; -import { PrismaHealthIndicatorUseCase } from '../../domain/usecases/prisma.health-indicator.usecase'; -import { MESSAGE_PUBLISHER } from 'src/app.constants'; -import { IPublishMessage } from 'src/interfaces/message-publisher'; - -@Controller('health') -export class HealthController { - constructor( - private readonly prismaHealthIndicatorUseCase: PrismaHealthIndicatorUseCase, - private readonly healthCheckService: HealthCheckService, - @Inject(MESSAGE_PUBLISHER) - private readonly messagePublisher: IPublishMessage, - ) {} - - @Get() - @HealthCheck() - async check() { - try { - return await this.healthCheckService.check([ - async () => this.prismaHealthIndicatorUseCase.isHealthy('prisma'), - ]); - } catch (error) { - const healthCheckResult: HealthCheckResult = error.response; - this.messagePublisher.publish( - 'logging.user.health.crit', - JSON.stringify(healthCheckResult.error), - ); - throw error; - } - } -} diff --git a/src/modules/health/adapters/secondaries/message-publisher.ts b/src/modules/health/adapters/secondaries/message-publisher.ts deleted file mode 100644 index 98a963b..0000000 --- a/src/modules/health/adapters/secondaries/message-publisher.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import { MESSAGE_BROKER_PUBLISHER } from '../../../../app.constants'; -import { MessageBrokerPublisher } from '@mobicoop/message-broker-module'; -import { IPublishMessage } from 'src/interfaces/message-publisher'; - -@Injectable() -export class MessagePublisher implements IPublishMessage { - constructor( - @Inject(MESSAGE_BROKER_PUBLISHER) - private readonly messageBrokerPublisher: MessageBrokerPublisher, - ) {} - - publish = (routingKey: string, message: string): void => { - this.messageBrokerPublisher.publish(routingKey, message); - }; -} diff --git a/src/modules/health/domain/usecases/prisma.health-indicator.usecase.ts b/src/modules/health/domain/usecases/prisma.health-indicator.usecase.ts deleted file mode 100644 index e30a617..0000000 --- a/src/modules/health/domain/usecases/prisma.health-indicator.usecase.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { - HealthCheckError, - HealthIndicator, - HealthIndicatorResult, -} from '@nestjs/terminus'; -import { UsersRepository } from '../../../user/adapters/secondaries/users.repository'; - -@Injectable() -export class PrismaHealthIndicatorUseCase extends HealthIndicator { - constructor(private readonly repository: UsersRepository) { - super(); - } - - isHealthy = async (key: string): Promise => { - try { - await this.repository.healthCheck(); - return this.getStatus(key, true); - } catch (e) { - throw new HealthCheckError('Prisma', { - prisma: e.message, - }); - } - }; -} diff --git a/src/modules/health/health.module.ts b/src/modules/health/health.module.ts deleted file mode 100644 index d84565b..0000000 --- a/src/modules/health/health.module.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Module } from '@nestjs/common'; -import { HealthServerController } from './adapters/primaries/health-server.controller'; -import { PrismaHealthIndicatorUseCase } from './domain/usecases/prisma.health-indicator.usecase'; -import { UsersRepository } from '../user/adapters/secondaries/users.repository'; -import { DatabaseModule } from '../database/database.module'; -import { HealthController } from './adapters/primaries/health.controller'; -import { TerminusModule } from '@nestjs/terminus'; -import { MESSAGE_BROKER_PUBLISHER, MESSAGE_PUBLISHER } from 'src/app.constants'; -import { MessageBrokerPublisher } from '@mobicoop/message-broker-module'; -import { MessagePublisher } from './adapters/secondaries/message-publisher'; - -@Module({ - imports: [TerminusModule, DatabaseModule], - controllers: [HealthServerController, HealthController], - providers: [ - PrismaHealthIndicatorUseCase, - UsersRepository, - { - provide: MESSAGE_BROKER_PUBLISHER, - useClass: MessageBrokerPublisher, - }, - { - provide: MESSAGE_PUBLISHER, - useClass: MessagePublisher, - }, - ], -}) -export class HealthModule {} diff --git a/src/modules/health/tests/unit/message-publisher.spec.ts b/src/modules/health/tests/unit/message-publisher.spec.ts deleted file mode 100644 index eec02ea..0000000 --- a/src/modules/health/tests/unit/message-publisher.spec.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { MessagePublisher } from '../../adapters/secondaries/message-publisher'; -import { MESSAGE_BROKER_PUBLISHER } from '../../../../app.constants'; - -const mockMessageBrokerPublisher = { - publish: jest.fn().mockImplementation(), -}; - -describe('Messager', () => { - let messagePublisher: MessagePublisher; - - beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ - imports: [], - providers: [ - MessagePublisher, - { - provide: MESSAGE_BROKER_PUBLISHER, - useValue: mockMessageBrokerPublisher, - }, - ], - }).compile(); - - messagePublisher = module.get(MessagePublisher); - }); - - it('should be defined', () => { - expect(messagePublisher).toBeDefined(); - }); - - it('should publish a message', async () => { - jest.spyOn(mockMessageBrokerPublisher, 'publish'); - messagePublisher.publish('health.info', 'my-test'); - expect(mockMessageBrokerPublisher.publish).toHaveBeenCalledTimes(1); - }); -}); diff --git a/src/modules/health/tests/unit/prisma.health-indicator.usecase.spec.ts b/src/modules/health/tests/unit/prisma.health-indicator.usecase.spec.ts deleted file mode 100644 index 3bc9312..0000000 --- a/src/modules/health/tests/unit/prisma.health-indicator.usecase.spec.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { PrismaHealthIndicatorUseCase } from '../../domain/usecases/prisma.health-indicator.usecase'; -import { UsersRepository } from '../../../user/adapters/secondaries/users.repository'; -import { HealthCheckError, HealthIndicatorResult } from '@nestjs/terminus'; -import { Prisma } from '@prisma/client'; - -const mockUsersRepository = { - healthCheck: jest - .fn() - .mockImplementationOnce(() => { - return Promise.resolve(true); - }) - .mockImplementation(() => { - throw new Prisma.PrismaClientKnownRequestError('Service unavailable', { - code: 'code', - clientVersion: 'version', - }); - }), -}; - -describe('PrismaHealthIndicatorUseCase', () => { - let prismaHealthIndicatorUseCase: PrismaHealthIndicatorUseCase; - - beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - { - provide: UsersRepository, - useValue: mockUsersRepository, - }, - PrismaHealthIndicatorUseCase, - ], - }).compile(); - - prismaHealthIndicatorUseCase = module.get( - PrismaHealthIndicatorUseCase, - ); - }); - - it('should be defined', () => { - expect(prismaHealthIndicatorUseCase).toBeDefined(); - }); - - describe('execute', () => { - it('should check health successfully', async () => { - const healthIndicatorResult: HealthIndicatorResult = - await prismaHealthIndicatorUseCase.isHealthy('prisma'); - - expect(healthIndicatorResult['prisma'].status).toBe('up'); - }); - - it('should throw an error if database is unavailable', async () => { - await expect( - prismaHealthIndicatorUseCase.isHealthy('prisma'), - ).rejects.toBeInstanceOf(HealthCheckError); - }); - }); -}); diff --git a/src/modules/messager/messager.di-tokens.ts b/src/modules/messager/messager.di-tokens.ts new file mode 100644 index 0000000..48e8011 --- /dev/null +++ b/src/modules/messager/messager.di-tokens.ts @@ -0,0 +1 @@ +export const MESSAGE_PUBLISHER = Symbol('MESSAGE_PUBLISHER'); diff --git a/src/modules/messager/messager.module.ts b/src/modules/messager/messager.module.ts new file mode 100644 index 0000000..c588861 --- /dev/null +++ b/src/modules/messager/messager.module.ts @@ -0,0 +1,36 @@ +import { Module, Provider } from '@nestjs/common'; +import { MESSAGE_PUBLISHER } from './messager.di-tokens'; +import { + MessageBrokerModule, + MessageBrokerModuleOptions, + MessageBrokerPublisher, +} from '@mobicoop/message-broker-module'; +import { ConfigModule, ConfigService } from '@nestjs/config'; + +const imports = [ + MessageBrokerModule.forRootAsync({ + imports: [ConfigModule], + inject: [ConfigService], + useFactory: async ( + configService: ConfigService, + ): Promise => ({ + uri: configService.get('MESSAGE_BROKER_URI'), + exchange: configService.get('MESSAGE_BROKER_EXCHANGE'), + name: 'user', + }), + }), +]; + +const providers: Provider[] = [ + { + provide: MESSAGE_PUBLISHER, + useClass: MessageBrokerPublisher, + }, +]; + +@Module({ + imports, + providers, + exports: [MESSAGE_PUBLISHER], +}) +export class MessagerModule {} diff --git a/src/modules/user/core/application/commands/create-user/create-user.command.ts b/src/modules/user/core/application/commands/create-user/create-user.command.ts new file mode 100644 index 0000000..d7bb7c6 --- /dev/null +++ b/src/modules/user/core/application/commands/create-user/create-user.command.ts @@ -0,0 +1,16 @@ +import { Command, CommandProps } from '@mobicoop/ddd-library'; + +export class CreateUserCommand extends Command { + readonly firstName?: string; + readonly lastName?: string; + readonly email?: string; + readonly phone?: string; + + constructor(props: CommandProps) { + super(props); + this.firstName = props.firstName; + this.lastName = props.lastName; + this.email = props.email; + this.phone = props.phone; + } +} diff --git a/src/modules/user/core/application/commands/create-user/create-user.service.ts b/src/modules/user/core/application/commands/create-user/create-user.service.ts new file mode 100644 index 0000000..077ca82 --- /dev/null +++ b/src/modules/user/core/application/commands/create-user/create-user.service.ts @@ -0,0 +1,35 @@ +import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'; +import { Inject } from '@nestjs/common'; +import { AggregateID, ConflictException } from '@mobicoop/ddd-library'; +import { CreateUserCommand } from './create-user.command'; +import { USER_REPOSITORY } from '@modules/user/user.di-tokens'; +import { UserRepositoryPort } from '../../ports/user.repository.port'; +import { UserEntity } from '../../../domain/user.entity'; +import { UserAlreadyExistsException } from '../../../domain/user.errors'; + +@CommandHandler(CreateUserCommand) +export class CreateUserService implements ICommandHandler { + constructor( + @Inject(USER_REPOSITORY) + private readonly repository: UserRepositoryPort, + ) {} + + async execute(command: CreateUserCommand): Promise { + const user = UserEntity.create({ + firstName: command.firstName, + lastName: command.lastName, + email: command.email, + phone: command.phone, + }); + + try { + await this.repository.insert(user); + return user.id; + } catch (error: any) { + if (error instanceof ConflictException) { + throw new UserAlreadyExistsException(error); + } + throw error; + } + } +} diff --git a/src/modules/user/core/application/commands/update-user/update-user.command.ts b/src/modules/user/core/application/commands/update-user/update-user.command.ts new file mode 100644 index 0000000..98fd5bb --- /dev/null +++ b/src/modules/user/core/application/commands/update-user/update-user.command.ts @@ -0,0 +1,16 @@ +import { Command, CommandProps } from '@mobicoop/ddd-library'; + +export class UpdateUserCommand extends Command { + readonly firstName?: string; + readonly lastName?: string; + readonly email?: string; + readonly phone?: string; + + constructor(props: CommandProps) { + super(props); + this.firstName = props.firstName; + this.lastName = props.lastName; + this.email = props.email; + this.phone = props.phone; + } +} diff --git a/src/modules/user/core/application/commands/update-user/update-user.service.ts b/src/modules/user/core/application/commands/update-user/update-user.service.ts new file mode 100644 index 0000000..78d6241 --- /dev/null +++ b/src/modules/user/core/application/commands/update-user/update-user.service.ts @@ -0,0 +1,57 @@ +import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'; +import { Inject } from '@nestjs/common'; +import { + AggregateID, + ConflictException, + UniqueConstraintException, +} from '@mobicoop/ddd-library'; +import { USER_REPOSITORY } from '@modules/user/user.di-tokens'; +import { UserRepositoryPort } from '../../ports/user.repository.port'; +import { UserEntity } from '../../../domain/user.entity'; +import { UpdateUserCommand } from './update-user.command'; +import { + EmailAlreadyExistsException, + PhoneAlreadyExistsException, + UserAlreadyExistsException, +} from '@modules/user/core/domain/user.errors'; + +@CommandHandler(UpdateUserCommand) +export class UpdateUserService implements ICommandHandler { + constructor( + @Inject(USER_REPOSITORY) + private readonly userRepository: UserRepositoryPort, + ) {} + + async execute(command: UpdateUserCommand): Promise { + try { + const user: UserEntity = await this.userRepository.findOneById( + command.id, + ); + user.update({ + firstName: command.firstName, + lastName: command.lastName, + email: command.email, + phone: command.phone, + }); + await this.userRepository.update(user.id, user); + return user.id; + } catch (error: any) { + if (error instanceof ConflictException) { + throw new UserAlreadyExistsException(error); + } + if ( + error instanceof UniqueConstraintException && + error.message.includes('email') + ) { + throw new EmailAlreadyExistsException(error); + } + if ( + error instanceof UniqueConstraintException && + error.message.includes('phone') + ) { + throw new PhoneAlreadyExistsException(error); + } + throw error; + } + } +} diff --git a/src/modules/user/core/application/ports/user.repository.port.ts b/src/modules/user/core/application/ports/user.repository.port.ts new file mode 100644 index 0000000..301f865 --- /dev/null +++ b/src/modules/user/core/application/ports/user.repository.port.ts @@ -0,0 +1,4 @@ +import { RepositoryPort } from '@mobicoop/ddd-library'; +import { UserEntity } from '../../domain/user.entity'; + +export type UserRepositoryPort = RepositoryPort; diff --git a/src/modules/user/core/domain/events/user-created.domain-events.ts b/src/modules/user/core/domain/events/user-created.domain-events.ts new file mode 100644 index 0000000..9d2ba93 --- /dev/null +++ b/src/modules/user/core/domain/events/user-created.domain-events.ts @@ -0,0 +1,16 @@ +import { DomainEvent, DomainEventProps } from '@mobicoop/ddd-library'; + +export class UserCreatedDomainEvent extends DomainEvent { + readonly firstName: string; + readonly lastName: string; + readonly email: string; + readonly phone: string; + + constructor(props: DomainEventProps) { + super(props); + this.firstName = props.firstName; + this.lastName = props.lastName; + this.email = props.email; + this.phone = props.phone; + } +} diff --git a/src/modules/user/core/domain/events/user-updated.domain-events.ts b/src/modules/user/core/domain/events/user-updated.domain-events.ts new file mode 100644 index 0000000..6911679 --- /dev/null +++ b/src/modules/user/core/domain/events/user-updated.domain-events.ts @@ -0,0 +1,16 @@ +import { DomainEvent, DomainEventProps } from '@mobicoop/ddd-library'; + +export class UserUpdatedDomainEvent extends DomainEvent { + readonly firstName: string; + readonly lastName: string; + readonly email: string; + readonly phone: string; + + constructor(props: DomainEventProps) { + super(props); + this.firstName = props.firstName; + this.lastName = props.lastName; + this.email = props.email; + this.phone = props.phone; + } +} diff --git a/src/modules/user/core/domain/user.entity.ts b/src/modules/user/core/domain/user.entity.ts new file mode 100644 index 0000000..8ec3605 --- /dev/null +++ b/src/modules/user/core/domain/user.entity.ts @@ -0,0 +1,46 @@ +import { AggregateRoot, AggregateID } from '@mobicoop/ddd-library'; +import { v4 } from 'uuid'; +import { CreateUserProps, UpdateUserProps, UserProps } from './user.types'; +import { UserCreatedDomainEvent } from './events/user-created.domain-events'; +import { UserUpdatedDomainEvent } from './events/user-updated.domain-events'; + +export class UserEntity extends AggregateRoot { + protected readonly _id: AggregateID; + + static create = (create: CreateUserProps): UserEntity => { + const id = v4(); + const props: UserProps = { ...create }; + const user = new UserEntity({ id, props }); + + user.addEvent( + new UserCreatedDomainEvent({ + aggregateId: id, + firstName: props.firstName, + lastName: props.lastName, + email: props.email, + phone: props.phone, + }), + ); + return user; + }; + + update(props: UpdateUserProps): void { + this.props.firstName = props.firstName; + this.props.lastName = props.lastName; + this.props.email = props.email; + this.props.phone = props.phone; + this.addEvent( + new UserUpdatedDomainEvent({ + aggregateId: this._id, + firstName: props.firstName, + lastName: props.lastName, + email: props.email, + phone: props.phone, + }), + ); + } + + validate(): void { + // entity business rules validation to protect it's invariant before saving entity to a database + } +} diff --git a/src/modules/user/core/domain/user.errors.ts b/src/modules/user/core/domain/user.errors.ts new file mode 100644 index 0000000..e3ff588 --- /dev/null +++ b/src/modules/user/core/domain/user.errors.ts @@ -0,0 +1,31 @@ +import { ExceptionBase } from '@mobicoop/ddd-library'; + +export class UserAlreadyExistsException extends ExceptionBase { + static readonly message = 'User already exists'; + + public readonly code = 'USER.ALREADY_EXISTS'; + + constructor(cause?: Error, metadata?: unknown) { + super(UserAlreadyExistsException.message, cause, metadata); + } +} + +export class EmailAlreadyExistsException extends ExceptionBase { + static readonly message = 'Email already exists'; + + public readonly code = 'EMAIL.ALREADY_EXISTS'; + + constructor(cause?: Error, metadata?: unknown) { + super(EmailAlreadyExistsException.message, cause, metadata); + } +} + +export class PhoneAlreadyExistsException extends ExceptionBase { + static readonly message = 'Phone already exists'; + + public readonly code = 'PHONE.ALREADY_EXISTS'; + + constructor(cause?: Error, metadata?: unknown) { + super(PhoneAlreadyExistsException.message, cause, metadata); + } +} diff --git a/src/modules/user/core/domain/user.types.ts b/src/modules/user/core/domain/user.types.ts new file mode 100644 index 0000000..d2c8782 --- /dev/null +++ b/src/modules/user/core/domain/user.types.ts @@ -0,0 +1,22 @@ +// All properties that a User has +export interface UserProps { + firstName: string; + lastName: string; + email: string; + phone: string; +} + +// Properties that are needed for a User creation +export interface CreateUserProps { + firstName: string; + lastName: string; + email: string; + phone: string; +} + +export interface UpdateUserProps { + firstName: string; + lastName: string; + email: string; + phone: string; +} diff --git a/src/modules/database/adapters/secondaries/prisma-service.ts b/src/modules/user/infrastructure/prisma.service.ts similarity index 100% rename from src/modules/database/adapters/secondaries/prisma-service.ts rename to src/modules/user/infrastructure/prisma.service.ts diff --git a/src/modules/user/infrastructure/user.repository.ts b/src/modules/user/infrastructure/user.repository.ts new file mode 100644 index 0000000..537961c --- /dev/null +++ b/src/modules/user/infrastructure/user.repository.ts @@ -0,0 +1,51 @@ +import { Inject, Injectable, Logger } from '@nestjs/common'; +import { EventEmitter2 } from '@nestjs/event-emitter'; +import { + LoggerBase, + MessagePublisherPort, + PrismaRepositoryBase, +} from '@mobicoop/ddd-library'; +import { PrismaService } from './prisma.service'; +import { UserEntity } from '../core/domain/user.entity'; +import { UserRepositoryPort } from '../core/application/ports/user.repository.port'; +import { UserMapper } from '../user.mapper'; +import { USER_MESSAGE_PUBLISHER } from '../user.di-tokens'; + +export type UserModel = { + uuid: string; + firstName: string; + lastName: string; + email: string; + phone: string; + createdAt: Date; + updatedAt: Date; +}; + +/** + * Repository is used for retrieving/saving domain entities + * */ +@Injectable() +export class UserRepository + extends PrismaRepositoryBase + implements UserRepositoryPort +{ + constructor( + prisma: PrismaService, + mapper: UserMapper, + eventEmitter: EventEmitter2, + @Inject(USER_MESSAGE_PUBLISHER) + protected readonly messagePublisher: MessagePublisherPort, + ) { + super( + prisma.user, + prisma, + mapper, + eventEmitter, + new LoggerBase({ + logger: new Logger(UserRepository.name), + domain: 'user', + messagePublisher, + }), + ); + } +} diff --git a/src/modules/user/interface/dtos/grpc-controllers/create-user.grpc.controller.ts b/src/modules/user/interface/dtos/grpc-controllers/create-user.grpc.controller.ts new file mode 100644 index 0000000..e234c5b --- /dev/null +++ b/src/modules/user/interface/dtos/grpc-controllers/create-user.grpc.controller.ts @@ -0,0 +1,41 @@ +import { Controller, UsePipes } from '@nestjs/common'; +import { CommandBus } from '@nestjs/cqrs'; +import { GrpcMethod, RpcException } from '@nestjs/microservices'; +import { AggregateID } from '@mobicoop/ddd-library'; +import { IdResponse } from '@mobicoop/ddd-library'; +import { RpcExceptionCode } from '@mobicoop/ddd-library'; +import { RpcValidationPipe } from '@mobicoop/ddd-library'; +import { CreateUserRequestDto } from './dtos/create-user.request.dto'; +import { CreateUserCommand } from '@modules/user/core/application/commands/create-user/create-user.command'; +import { UserAlreadyExistsException } from '@modules/user/core/domain/user.errors'; + +@UsePipes( + new RpcValidationPipe({ + whitelist: false, + forbidUnknownValues: false, + }), +) +@Controller() +export class CreateUserGrpcController { + constructor(private readonly commandBus: CommandBus) {} + + @GrpcMethod('UserService', 'Create') + async create(data: CreateUserRequestDto): Promise { + try { + const aggregateID: AggregateID = await this.commandBus.execute( + new CreateUserCommand(data), + ); + return new IdResponse(aggregateID); + } catch (error: any) { + if (error instanceof UserAlreadyExistsException) + throw new RpcException({ + code: RpcExceptionCode.ALREADY_EXISTS, + message: error.message, + }); + throw new RpcException({ + code: RpcExceptionCode.UNKNOWN, + message: error.message, + }); + } + } +} diff --git a/src/modules/user/interface/dtos/grpc-controllers/dtos/create-user.request.dto.ts b/src/modules/user/interface/dtos/grpc-controllers/dtos/create-user.request.dto.ts new file mode 100644 index 0000000..9736173 --- /dev/null +++ b/src/modules/user/interface/dtos/grpc-controllers/dtos/create-user.request.dto.ts @@ -0,0 +1,19 @@ +import { IsEmail, IsOptional, IsPhoneNumber, IsString } from 'class-validator'; + +export class CreateUserRequestDto { + @IsString() + @IsOptional() + firstName: string; + + @IsString() + @IsOptional() + lastName: string; + + @IsEmail() + @IsOptional() + email?: string; + + @IsPhoneNumber() + @IsOptional() + phone?: string; +} diff --git a/src/modules/user/interface/dtos/grpc-controllers/dtos/update-user.request.dto.ts b/src/modules/user/interface/dtos/grpc-controllers/dtos/update-user.request.dto.ts new file mode 100644 index 0000000..9c9a6d7 --- /dev/null +++ b/src/modules/user/interface/dtos/grpc-controllers/dtos/update-user.request.dto.ts @@ -0,0 +1,22 @@ +import { IsEmail, IsOptional, IsPhoneNumber, IsString } from 'class-validator'; + +export class UpdateUserRequestDto { + @IsString() + id: string; + + @IsString() + @IsOptional() + firstName?: string; + + @IsString() + @IsOptional() + lastName?: string; + + @IsEmail() + @IsOptional() + email?: string; + + @IsPhoneNumber() + @IsOptional() + phone?: string; +} diff --git a/src/modules/user/interface/dtos/grpc-controllers/update-user.grpc.controller.ts b/src/modules/user/interface/dtos/grpc-controllers/update-user.grpc.controller.ts new file mode 100644 index 0000000..c5df8cb --- /dev/null +++ b/src/modules/user/interface/dtos/grpc-controllers/update-user.grpc.controller.ts @@ -0,0 +1,56 @@ +import { + AggregateID, + IdResponse, + RpcExceptionCode, + RpcValidationPipe, +} from '@mobicoop/ddd-library'; +import { Controller, UsePipes } from '@nestjs/common'; +import { CommandBus } from '@nestjs/cqrs'; +import { GrpcMethod, RpcException } from '@nestjs/microservices'; +import { UpdateUserRequestDto } from './dtos/update-user.request.dto'; +import { UpdateUserCommand } from '@modules/user/core/application/commands/update-user/update-user.command'; +import { + EmailAlreadyExistsException, + PhoneAlreadyExistsException, + UserAlreadyExistsException, +} from '@modules/user/core/domain/user.errors'; + +@UsePipes( + new RpcValidationPipe({ + whitelist: true, + forbidUnknownValues: false, + }), +) +@Controller() +export class UpdateUserGrpcController { + constructor(private readonly commandBus: CommandBus) {} + + @GrpcMethod('UserService', 'UpdateUser') + async updateUser(data: UpdateUserRequestDto): Promise { + try { + const aggregateID: AggregateID = await this.commandBus.execute( + new UpdateUserCommand({ + firstName: data.firstName, + lastName: data.lastName, + email: data.email, + phone: data.phone, + }), + ); + return new IdResponse(aggregateID); + } catch (error: any) { + if ( + error instanceof UserAlreadyExistsException || + error instanceof EmailAlreadyExistsException || + error instanceof PhoneAlreadyExistsException + ) + throw new RpcException({ + code: RpcExceptionCode.ALREADY_EXISTS, + message: error.message, + }); + throw new RpcException({ + code: RpcExceptionCode.UNKNOWN, + message: error.message, + }); + } + } +} diff --git a/src/modules/user/interface/dtos/grpc-controllers/user.proto b/src/modules/user/interface/dtos/grpc-controllers/user.proto new file mode 100644 index 0000000..cde99ea --- /dev/null +++ b/src/modules/user/interface/dtos/grpc-controllers/user.proto @@ -0,0 +1,35 @@ +syntax = "proto3"; + +package user; + +service UserService { + rpc FindOneByUuid(UserByUuid) returns (User); + rpc FindAll(UserFilter) returns (Users); + rpc Create(User) returns (User); + rpc Update(User) returns (User); + rpc Delete(UserByUuid) returns (Empty); +} + +message UserByUuid { + string uuid = 1; +} + +message User { + string uuid = 1; + string firstName = 2; + string lastName = 3; + string email = 4; + string phone = 5; +} + +message UserFilter { + optional int32 page = 1; + optional int32 perPage = 2; +} + +message Users { + repeated User data = 1; + int32 total = 2; +} + +message Empty {} diff --git a/src/modules/user/interface/dtos/user.paginated.response.dto.ts b/src/modules/user/interface/dtos/user.paginated.response.dto.ts new file mode 100644 index 0000000..96e8cd5 --- /dev/null +++ b/src/modules/user/interface/dtos/user.paginated.response.dto.ts @@ -0,0 +1,6 @@ +import { PaginatedResponseDto } from '@mobicoop/ddd-library'; +import { UserResponseDto } from './user.response.dto'; + +export class UserPaginatedResponseDto extends PaginatedResponseDto { + readonly data: readonly UserResponseDto[]; +} diff --git a/src/modules/user/interface/dtos/user.response.dto.ts b/src/modules/user/interface/dtos/user.response.dto.ts new file mode 100644 index 0000000..13e62ff --- /dev/null +++ b/src/modules/user/interface/dtos/user.response.dto.ts @@ -0,0 +1,8 @@ +import { ResponseBase } from '@mobicoop/ddd-library'; + +export class UserResponseDto extends ResponseBase { + firstName: string; + lastName: string; + email: string; + phone: string; +} diff --git a/src/modules/user/adapters/primaries/user.controller.ts b/src/modules/user/old/adapters/primaries/user.controller.ts similarity index 100% rename from src/modules/user/adapters/primaries/user.controller.ts rename to src/modules/user/old/adapters/primaries/user.controller.ts diff --git a/src/modules/user/adapters/primaries/user.presenter.ts b/src/modules/user/old/adapters/primaries/user.presenter.ts similarity index 100% rename from src/modules/user/adapters/primaries/user.presenter.ts rename to src/modules/user/old/adapters/primaries/user.presenter.ts diff --git a/src/modules/user/adapters/primaries/user.proto b/src/modules/user/old/adapters/primaries/user.proto similarity index 100% rename from src/modules/user/adapters/primaries/user.proto rename to src/modules/user/old/adapters/primaries/user.proto diff --git a/src/modules/user/adapters/secondaries/message-publisher.ts b/src/modules/user/old/adapters/secondaries/message-publisher.ts similarity index 100% rename from src/modules/user/adapters/secondaries/message-publisher.ts rename to src/modules/user/old/adapters/secondaries/message-publisher.ts diff --git a/src/modules/user/adapters/secondaries/users.repository.ts b/src/modules/user/old/adapters/secondaries/users.repository.ts similarity index 100% rename from src/modules/user/adapters/secondaries/users.repository.ts rename to src/modules/user/old/adapters/secondaries/users.repository.ts diff --git a/src/modules/user/commands/create-user.command.ts b/src/modules/user/old/commands/create-user.command.ts similarity index 100% rename from src/modules/user/commands/create-user.command.ts rename to src/modules/user/old/commands/create-user.command.ts diff --git a/src/modules/user/commands/delete-user.command.ts b/src/modules/user/old/commands/delete-user.command.ts similarity index 100% rename from src/modules/user/commands/delete-user.command.ts rename to src/modules/user/old/commands/delete-user.command.ts diff --git a/src/modules/user/commands/update-user.command.ts b/src/modules/user/old/commands/update-user.command.ts similarity index 100% rename from src/modules/user/commands/update-user.command.ts rename to src/modules/user/old/commands/update-user.command.ts diff --git a/src/modules/user/domain/dtos/create-user.request.ts b/src/modules/user/old/domain/dtos/create-user.request.ts similarity index 100% rename from src/modules/user/domain/dtos/create-user.request.ts rename to src/modules/user/old/domain/dtos/create-user.request.ts diff --git a/src/modules/user/domain/dtos/find-all-users.request.ts b/src/modules/user/old/domain/dtos/find-all-users.request.ts similarity index 100% rename from src/modules/user/domain/dtos/find-all-users.request.ts rename to src/modules/user/old/domain/dtos/find-all-users.request.ts diff --git a/src/modules/user/domain/dtos/find-user-by-uuid.request.ts b/src/modules/user/old/domain/dtos/find-user-by-uuid.request.ts similarity index 100% rename from src/modules/user/domain/dtos/find-user-by-uuid.request.ts rename to src/modules/user/old/domain/dtos/find-user-by-uuid.request.ts diff --git a/src/modules/user/domain/dtos/update-user.request.ts b/src/modules/user/old/domain/dtos/update-user.request.ts similarity index 100% rename from src/modules/user/domain/dtos/update-user.request.ts rename to src/modules/user/old/domain/dtos/update-user.request.ts diff --git a/src/modules/user/domain/entities/user.ts b/src/modules/user/old/domain/entities/user.ts similarity index 100% rename from src/modules/user/domain/entities/user.ts rename to src/modules/user/old/domain/entities/user.ts diff --git a/src/modules/user/domain/usecases/create-user.usecase.ts b/src/modules/user/old/domain/usecases/create-user.usecase.ts similarity index 100% rename from src/modules/user/domain/usecases/create-user.usecase.ts rename to src/modules/user/old/domain/usecases/create-user.usecase.ts diff --git a/src/modules/user/domain/usecases/delete-user.usecase.ts b/src/modules/user/old/domain/usecases/delete-user.usecase.ts similarity index 100% rename from src/modules/user/domain/usecases/delete-user.usecase.ts rename to src/modules/user/old/domain/usecases/delete-user.usecase.ts diff --git a/src/modules/user/domain/usecases/find-all-users.usecase.ts b/src/modules/user/old/domain/usecases/find-all-users.usecase.ts similarity index 100% rename from src/modules/user/domain/usecases/find-all-users.usecase.ts rename to src/modules/user/old/domain/usecases/find-all-users.usecase.ts diff --git a/src/modules/user/domain/usecases/find-user-by-uuid.usecase.ts b/src/modules/user/old/domain/usecases/find-user-by-uuid.usecase.ts similarity index 100% rename from src/modules/user/domain/usecases/find-user-by-uuid.usecase.ts rename to src/modules/user/old/domain/usecases/find-user-by-uuid.usecase.ts diff --git a/src/modules/user/domain/usecases/update-user.usecase.ts b/src/modules/user/old/domain/usecases/update-user.usecase.ts similarity index 100% rename from src/modules/user/domain/usecases/update-user.usecase.ts rename to src/modules/user/old/domain/usecases/update-user.usecase.ts diff --git a/src/modules/user/mappers/user.profile.ts b/src/modules/user/old/mappers/user.profile.ts similarity index 100% rename from src/modules/user/mappers/user.profile.ts rename to src/modules/user/old/mappers/user.profile.ts diff --git a/src/modules/user/queries/find-all-users.query.ts b/src/modules/user/old/queries/find-all-users.query.ts similarity index 100% rename from src/modules/user/queries/find-all-users.query.ts rename to src/modules/user/old/queries/find-all-users.query.ts diff --git a/src/modules/user/queries/find-user-by-uuid.query.ts b/src/modules/user/old/queries/find-user-by-uuid.query.ts similarity index 100% rename from src/modules/user/queries/find-user-by-uuid.query.ts rename to src/modules/user/old/queries/find-user-by-uuid.query.ts diff --git a/src/modules/user/tests/unit/find-all-users.usecase.spec.ts b/src/modules/user/old/tests/unit/find-all-users.usecase.spec.ts similarity index 100% rename from src/modules/user/tests/unit/find-all-users.usecase.spec.ts rename to src/modules/user/old/tests/unit/find-all-users.usecase.spec.ts diff --git a/src/modules/user/tests/unit/find-user-by-uuid.usecase.spec.ts b/src/modules/user/old/tests/unit/find-user-by-uuid.usecase.spec.ts similarity index 100% rename from src/modules/user/tests/unit/find-user-by-uuid.usecase.spec.ts rename to src/modules/user/old/tests/unit/find-user-by-uuid.usecase.spec.ts diff --git a/src/modules/user/tests/integration/user.repository.spec.ts b/src/modules/user/tests/integration/user.repository.spec.ts new file mode 100644 index 0000000..405e4e1 --- /dev/null +++ b/src/modules/user/tests/integration/user.repository.spec.ts @@ -0,0 +1,119 @@ +import { UserEntity } from '@modules/user/core/domain/user.entity'; +import { CreateUserProps } from '@modules/user/core/domain/user.types'; +import { PrismaService } from '@modules/user/infrastructure/prisma.service'; +import { UserRepository } from '@modules/user/infrastructure/user.repository'; +import { + USER_MESSAGE_PUBLISHER, + USER_REPOSITORY, +} from '@modules/user/user.di-tokens'; +import { UserMapper } from '@modules/user/user.mapper'; +import { ConfigModule } from '@nestjs/config'; +import { EventEmitterModule } from '@nestjs/event-emitter'; +import { Test } from '@nestjs/testing'; + +describe('User Repository', () => { + let prismaService: PrismaService; + let userRepository: UserRepository; + + const executeInsertCommand = async (table: string, object: any) => { + const command = `INSERT INTO ${table} ("${Object.keys(object).join( + '","', + )}") VALUES (${Object.values(object).join(',')})`; + + await prismaService.$executeRawUnsafe(command); + }; + const getSeed = (index: number, uuid: string): string => { + return `'${uuid.slice(0, -2)}${index.toString(16).padStart(2, '0')}'`; + }; + + const baseUuid = { + uuid: 'be459a29-7a41-4c0b-b371-abe90bfb6f00', + }; + + const createUsers = async (nbToCreate = 10) => { + for (let i = 0; i < nbToCreate; i++) { + const userToCreate = { + uuid: getSeed(i, baseUuid.uuid), + firstName: `John${i}`, + lastName: `Doe${i}`, + email: `john.doe${i}@email.com`, + phone: `+33611223344${i}`, + }; + userToCreate.uuid = getSeed(i, baseUuid.uuid); + await executeInsertCommand('user', userToCreate); + } + }; + + const mockMessagePublisher = { + publish: jest.fn().mockImplementation(), + }; + + const mockLogger = { + log: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; + + beforeAll(async () => { + const module = await Test.createTestingModule({ + imports: [ + EventEmitterModule.forRoot(), + ConfigModule.forRoot({ isGlobal: true }), + ], + providers: [ + PrismaService, + UserMapper, + { + provide: USER_REPOSITORY, + useClass: UserRepository, + }, + { + provide: USER_MESSAGE_PUBLISHER, + useValue: mockMessagePublisher, + }, + ], + }) + // disable logging + .setLogger(mockLogger) + .compile(); + + prismaService = module.get(PrismaService); + userRepository = module.get(USER_REPOSITORY); + }); + + afterAll(async () => { + await prismaService.$disconnect(); + }); + + beforeEach(async () => { + await prismaService.user.deleteMany(); + }); + + describe('findOneById', () => { + it('should return a user', async () => { + await createUsers(1); + const result = await userRepository.findOneById(baseUuid.uuid); + expect(result.id).toBe(baseUuid.uuid); + }); + }); + + describe('create', () => { + it('should create a user', async () => { + const beforeCount = await prismaService.user.count(); + + const createUserProps: CreateUserProps = { + firstName: 'Jane', + lastName: 'Doe', + email: 'jane.doe@email.com', + phone: '+33622334455', + }; + + const userToCreate: UserEntity = UserEntity.create(createUserProps); + await userRepository.insert(userToCreate); + + const afterCount = await prismaService.user.count(); + + expect(afterCount - beforeCount).toBe(1); + }); + }); +}); diff --git a/src/modules/user/tests/integration/users.repository.spec.ts b/src/modules/user/tests/integration/users.repository.spec.ts deleted file mode 100644 index e185654..0000000 --- a/src/modules/user/tests/integration/users.repository.spec.ts +++ /dev/null @@ -1,174 +0,0 @@ -import { TestingModule, Test } from '@nestjs/testing'; -import { DatabaseModule } from '../../../database/database.module'; -import { PrismaService } from '../../../database/adapters/secondaries/prisma-service'; -import { DatabaseException } from '../../../database/exceptions/database.exception'; -import { UsersRepository } from '../../adapters/secondaries/users.repository'; -import { User } from '../../domain/entities/user'; - -describe('UsersRepository', () => { - let prismaService: PrismaService; - let usersRepository: UsersRepository; - - const createUsers = async (nbToCreate = 10) => { - for (let i = 0; i < nbToCreate; i++) { - await prismaService.user.create({ - data: { - firstName: `firstName-${i}`, - }, - }); - } - }; - - beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ - imports: [DatabaseModule], - providers: [UsersRepository, PrismaService], - }).compile(); - - prismaService = module.get(PrismaService); - usersRepository = module.get(UsersRepository); - }); - - afterAll(async () => { - await prismaService.$disconnect(); - }); - - beforeEach(async () => { - await prismaService.user.deleteMany(); - }); - - describe('findAll', () => { - it('should return an empty data array', async () => { - const res = await usersRepository.findAll(); - expect(res).toEqual({ - data: [], - total: 0, - }); - }); - - it('should return a data array with 8 users', async () => { - await createUsers(8); - const users = await usersRepository.findAll(); - expect(users.data.length).toBe(8); - expect(users.total).toBe(8); - }); - - it('should return a data array limited to 10 users', async () => { - await createUsers(20); - const users = await usersRepository.findAll(); - expect(users.data.length).toBe(10); - expect(users.total).toBe(20); - }); - }); - - describe('findOneByUuid', () => { - it('should return a user', async () => { - const userToFind = await prismaService.user.create({ - data: { - firstName: 'test', - }, - }); - - const user = await usersRepository.findOneByUuid(userToFind.uuid); - expect(user.uuid).toBe(userToFind.uuid); - }); - - it('should return null', async () => { - const user = await usersRepository.findOneByUuid( - '544572be-11fb-4244-8235-587221fc9104', - ); - expect(user).toBeNull(); - }); - }); - - describe('findOne', () => { - it('should return a user according to its email', async () => { - const userToFind = await prismaService.user.create({ - data: { - email: 'test@test.com', - }, - }); - - const user = await usersRepository.findOne({ - email: 'test@test.com', - }); - - expect(user.uuid).toBe(userToFind.uuid); - }); - - it('should return null with unknown email', async () => { - const user = await usersRepository.findOne({ - email: 'wrong@email.com', - }); - expect(user).toBeNull(); - }); - }); - - describe('create', () => { - it('should create a user', async () => { - const beforeCount = await prismaService.user.count(); - - const userToCreate: User = new User(); - userToCreate.firstName = 'test'; - const user = await usersRepository.create(userToCreate); - - const afterCount = await prismaService.user.count(); - - expect(afterCount - beforeCount).toBe(1); - expect(user.uuid).toBeDefined(); - }); - }); - - describe('update', () => { - it('should update user firstName', async () => { - const userToUpdate = await prismaService.user.create({ - data: { - firstName: 'test', - }, - }); - - const toUpdate: User = new User(); - toUpdate.firstName = 'updated'; - const updateduser = await usersRepository.update( - userToUpdate.uuid, - toUpdate, - ); - - expect(updateduser.uuid).toBe(userToUpdate.uuid); - expect(updateduser.firstName).toBe('updated'); - }); - - it('should throw DatabaseException', async () => { - const toUpdate: User = new User(); - toUpdate.firstName = 'updated'; - - await expect( - usersRepository.update( - '544572be-11fb-4244-8235-587221fc9104', - toUpdate, - ), - ).rejects.toBeInstanceOf(DatabaseException); - }); - }); - - describe('delete', () => { - it('should delete a user', async () => { - const userToRemove = await prismaService.user.create({ - data: { - firstName: 'test', - }, - }); - - await usersRepository.delete(userToRemove.uuid); - - const count = await prismaService.user.count(); - expect(count).toBe(0); - }); - - it('should throw DatabaseException', async () => { - await expect( - usersRepository.delete('544572be-11fb-4244-8235-587221fc9104'), - ).rejects.toBeInstanceOf(DatabaseException); - }); - }); -}); diff --git a/src/modules/user/tests/unit/core/create-user.service.spec.ts b/src/modules/user/tests/unit/core/create-user.service.spec.ts new file mode 100644 index 0000000..32bb093 --- /dev/null +++ b/src/modules/user/tests/unit/core/create-user.service.spec.ts @@ -0,0 +1,79 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AggregateID } from '@mobicoop/ddd-library'; +import { ConflictException } from '@mobicoop/ddd-library'; +import { CreateUserRequestDto } from '@modules/user/interface/dtos/grpc-controllers/dtos/create-user.request.dto'; +import { CreateUserService } from '@modules/user/core/application/commands/create-user/create-user.service'; +import { USER_REPOSITORY } from '@modules/user/user.di-tokens'; +import { UserEntity } from '@modules/user/core/domain/user.entity'; +import { CreateUserCommand } from '@modules/user/core/application/commands/create-user/create-user.command'; +import { UserAlreadyExistsException } from '@modules/user/core/domain/user.errors'; + +const createUserRequest: CreateUserRequestDto = { + firstName: 'John', + lastName: 'Doe', + email: 'john.doe@email.com', + phone: '+33611223344', +}; + +const mockUserRepository = { + insert: jest + .fn() + .mockImplementationOnce(() => ({})) + .mockImplementationOnce(() => { + throw new Error(); + }) + .mockImplementationOnce(() => { + throw new ConflictException('already exists'); + }), +}; + +describe('create-user.service', () => { + let createUserService: CreateUserService; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: USER_REPOSITORY, + useValue: mockUserRepository, + }, + CreateUserService, + ], + }).compile(); + + createUserService = module.get(CreateUserService); + }); + + it('should be defined', () => { + expect(createUserService).toBeDefined(); + }); + + describe('execution', () => { + const createUserCommand = new CreateUserCommand(createUserRequest); + it('should create a new user', async () => { + UserEntity.create = jest.fn().mockReturnValue({ + id: '047a6ecf-23d4-4d3e-877c-3225d560a8da', + }); + const result: AggregateID = await createUserService.execute( + createUserCommand, + ); + expect(result).toBe('047a6ecf-23d4-4d3e-877c-3225d560a8da'); + }); + it('should throw an error if something bad happens', async () => { + UserEntity.create = jest.fn().mockReturnValue({ + id: '047a6ecf-23d4-4d3e-877c-3225d560a8da', + }); + await expect( + createUserService.execute(createUserCommand), + ).rejects.toBeInstanceOf(Error); + }); + it('should throw an exception if User already exists', async () => { + UserEntity.create = jest.fn().mockReturnValue({ + id: '047a6ecf-23d4-4d3e-877c-3225d560a8da', + }); + await expect( + createUserService.execute(createUserCommand), + ).rejects.toBeInstanceOf(UserAlreadyExistsException); + }); + }); +}); diff --git a/src/modules/user/tests/unit/core/user.entity.spec.ts b/src/modules/user/tests/unit/core/user.entity.spec.ts new file mode 100644 index 0000000..32aa437 --- /dev/null +++ b/src/modules/user/tests/unit/core/user.entity.spec.ts @@ -0,0 +1,17 @@ +import { UserEntity } from '@modules/user/core/domain/user.entity'; +import { CreateUserProps } from '@modules/user/core/domain/user.types'; + +const createUserProps: CreateUserProps = { + firstName: 'John', + lastName: 'Doe', + email: 'john.doe@email.com', + phone: '+33611223344', +}; + +describe('User entity create', () => { + it('should create a new user entity', async () => { + const userEntity: UserEntity = UserEntity.create(createUserProps); + expect(userEntity.id.length).toBe(36); + expect(userEntity.getProps().email).toBe('john.doe@email.com'); + }); +}); diff --git a/src/modules/user/tests/unit/create-user.usecase.spec.ts b/src/modules/user/tests/unit/create-user.usecase.spec.ts deleted file mode 100644 index 5b8db2f..0000000 --- a/src/modules/user/tests/unit/create-user.usecase.spec.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { classes } from '@automapper/classes'; -import { AutomapperModule } from '@automapper/nestjs'; -import { Test, TestingModule } from '@nestjs/testing'; -import { UsersRepository } from '../../adapters/secondaries/users.repository'; -import { CreateUserCommand } from '../../commands/create-user.command'; -import { CreateUserRequest } from '../../domain/dtos/create-user.request'; -import { User } from '../../domain/entities/user'; -import { CreateUserUseCase } from '../../domain/usecases/create-user.usecase'; -import { UserProfile } from '../../mappers/user.profile'; -import { MESSAGE_PUBLISHER } from '../../../../app.constants'; - -const newUserRequest: CreateUserRequest = { - firstName: 'John', - lastName: 'Doe', - email: 'john.doe@email.com', - phone: '0601020304', -}; -const newUserCommand: CreateUserCommand = new CreateUserCommand(newUserRequest); - -const mockUsersRepository = { - create: jest - .fn() - .mockImplementationOnce(() => { - return Promise.resolve({ - ...newUserRequest, - uuid: 'bb281075-1b98-4456-89d6-c643d3044a91', - }); - }) - .mockImplementation(() => { - throw new Error('Already exists'); - }), -}; - -const mockMessagePublisher = { - publish: jest.fn().mockImplementation(), -}; - -describe('CreateUserUseCase', () => { - let createUserUseCase: CreateUserUseCase; - - beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ - imports: [AutomapperModule.forRoot({ strategyInitializer: classes() })], - providers: [ - { - provide: UsersRepository, - useValue: mockUsersRepository, - }, - CreateUserUseCase, - UserProfile, - { - provide: MESSAGE_PUBLISHER, - useValue: mockMessagePublisher, - }, - ], - }).compile(); - - createUserUseCase = module.get(CreateUserUseCase); - }); - - it('should be defined', () => { - expect(createUserUseCase).toBeDefined(); - }); - - describe('execute', () => { - it('should create and return a new user', async () => { - const newUser: User = await createUserUseCase.execute(newUserCommand); - - expect(newUser.lastName).toBe(newUserRequest.lastName); - expect(newUser.uuid).toBeDefined(); - }); - - it('should throw an error if user already exists', async () => { - await expect( - createUserUseCase.execute(newUserCommand), - ).rejects.toBeInstanceOf(Error); - }); - }); -}); diff --git a/src/modules/user/tests/unit/delete-user.usecase.spec.ts b/src/modules/user/tests/unit/delete-user.usecase.spec.ts deleted file mode 100644 index acacc49..0000000 --- a/src/modules/user/tests/unit/delete-user.usecase.spec.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { UsersRepository } from '../../adapters/secondaries/users.repository'; -import { DeleteUserCommand } from '../../commands/delete-user.command'; -import { DeleteUserUseCase } from '../../domain/usecases/delete-user.usecase'; -import { MESSAGE_PUBLISHER } from '../../../../app.constants'; - -const mockUsers = [ - { - uuid: 'bb281075-1b98-4456-89d6-c643d3044a91', - firstName: 'John', - lastName: 'Doe', - email: 'john.doe@email.com', - phone: '0601020304', - }, - { - uuid: 'bb281075-1b98-4456-89d6-c643d3044a92', - firstName: 'Jane', - lastName: 'Doe', - email: 'jane.doe@email.com', - phone: '0602030405', - }, - { - uuid: 'bb281075-1b98-4456-89d6-c643d3044a93', - firstName: 'Jimmy', - lastName: 'Doe', - email: 'jimmy.doe@email.com', - phone: '0603040506', - }, -]; - -const mockUsersRepository = { - delete: jest - .fn() - .mockImplementationOnce((uuid: string) => { - let savedUser = {}; - mockUsers.forEach((user, index) => { - if (user.uuid === uuid) { - savedUser = { ...user }; - mockUsers.splice(index, 1); - } - }); - return savedUser; - }) - .mockImplementation(() => { - throw new Error('Error'); - }), -}; - -const mockMessagePublisher = { - publish: jest.fn().mockImplementation(), -}; - -describe('DeleteUserUseCase', () => { - let deleteUserUseCase: DeleteUserUseCase; - - beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - { - provide: UsersRepository, - useValue: mockUsersRepository, - }, - DeleteUserUseCase, - { - provide: MESSAGE_PUBLISHER, - useValue: mockMessagePublisher, - }, - ], - }).compile(); - - deleteUserUseCase = module.get(DeleteUserUseCase); - }); - - it('should be defined', () => { - expect(deleteUserUseCase).toBeDefined(); - }); - - describe('execute', () => { - it('should delete a user', async () => { - const savedUuid = mockUsers[0].uuid; - const deleteUserCommand = new DeleteUserCommand(savedUuid); - await deleteUserUseCase.execute(deleteUserCommand); - - const deletedUser = mockUsers.find((user) => user.uuid === savedUuid); - expect(deletedUser).toBeUndefined(); - }); - it('should throw an error if user does not exist', async () => { - await expect( - deleteUserUseCase.execute(new DeleteUserCommand('wrong uuid')), - ).rejects.toBeInstanceOf(Error); - }); - }); -}); diff --git a/src/modules/user/tests/unit/infrastructure/user.repository.spec.ts b/src/modules/user/tests/unit/infrastructure/user.repository.spec.ts new file mode 100644 index 0000000..8f68182 --- /dev/null +++ b/src/modules/user/tests/unit/infrastructure/user.repository.spec.ts @@ -0,0 +1,36 @@ +import { EventEmitter2, EventEmitterModule } from '@nestjs/event-emitter'; +import { Test, TestingModule } from '@nestjs/testing'; +import { PrismaService } from '@modules/user/infrastructure/prisma.service'; +import { UserRepository } from '@modules/user/infrastructure/user.repository'; +import { UserMapper } from '@modules/user/user.mapper'; + +const mockMessagePublisher = { + publish: jest.fn().mockImplementation(), +}; + +describe('User repository', () => { + let prismaService: PrismaService; + let userMapper: UserMapper; + let eventEmitter: EventEmitter2; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + imports: [EventEmitterModule.forRoot()], + providers: [PrismaService, UserMapper], + }).compile(); + + prismaService = module.get(PrismaService); + userMapper = module.get(UserMapper); + eventEmitter = module.get(EventEmitter2); + }); + it('should be defined', () => { + expect( + new UserRepository( + prismaService, + userMapper, + eventEmitter, + mockMessagePublisher, + ), + ).toBeDefined(); + }); +}); diff --git a/src/modules/user/tests/unit/interface/create-user.grpc.controller.spec.ts b/src/modules/user/tests/unit/interface/create-user.grpc.controller.spec.ts new file mode 100644 index 0000000..3d7acc0 --- /dev/null +++ b/src/modules/user/tests/unit/interface/create-user.grpc.controller.spec.ts @@ -0,0 +1,89 @@ +import { IdResponse } from '@mobicoop/ddd-library'; +import { RpcExceptionCode } from '@mobicoop/ddd-library'; +import { CommandBus } from '@nestjs/cqrs'; +import { RpcException } from '@nestjs/microservices'; +import { Test, TestingModule } from '@nestjs/testing'; +import { UserAlreadyExistsException } from '@modules/user/core/domain/user.errors'; +import { CreateUserGrpcController } from '@modules/user/interface/dtos/grpc-controllers/create-user.grpc.controller'; +import { CreateUserRequestDto } from '@modules/user/interface/dtos/grpc-controllers/dtos/create-user.request.dto'; + +const createUserRequest: CreateUserRequestDto = { + firstName: 'John', + lastName: 'Doe', + email: 'john.doe@email.com', + phone: '+33611223344', +}; + +const mockCommandBus = { + execute: jest + .fn() + .mockImplementationOnce(() => '200d61a8-d878-4378-a609-c19ea71633d2') + .mockImplementationOnce(() => { + throw new UserAlreadyExistsException(); + }) + .mockImplementationOnce(() => { + throw new Error(); + }), +}; + +describe('Create User Grpc Controller', () => { + let createUserGrpcController: CreateUserGrpcController; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: CommandBus, + useValue: mockCommandBus, + }, + CreateUserGrpcController, + ], + }).compile(); + + createUserGrpcController = module.get( + CreateUserGrpcController, + ); + }); + + afterEach(async () => { + jest.clearAllMocks(); + }); + + it('should be defined', () => { + expect(createUserGrpcController).toBeDefined(); + }); + + it('should create a new user', async () => { + jest.spyOn(mockCommandBus, 'execute'); + const result: IdResponse = await createUserGrpcController.create( + createUserRequest, + ); + expect(result).toBeInstanceOf(IdResponse); + expect(result.id).toBe('200d61a8-d878-4378-a609-c19ea71633d2'); + expect(mockCommandBus.execute).toHaveBeenCalledTimes(1); + }); + + it('should throw a dedicated RpcException if user already exists', async () => { + jest.spyOn(mockCommandBus, 'execute'); + expect.assertions(3); + try { + await createUserGrpcController.create(createUserRequest); + } catch (e: any) { + expect(e).toBeInstanceOf(RpcException); + expect(e.error.code).toBe(RpcExceptionCode.ALREADY_EXISTS); + } + expect(mockCommandBus.execute).toHaveBeenCalledTimes(1); + }); + + it('should throw a generic RpcException', async () => { + jest.spyOn(mockCommandBus, 'execute'); + expect.assertions(3); + try { + await createUserGrpcController.create(createUserRequest); + } catch (e: any) { + expect(e).toBeInstanceOf(RpcException); + expect(e.error.code).toBe(RpcExceptionCode.UNKNOWN); + } + expect(mockCommandBus.execute).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/modules/user/tests/unit/interface/update-user.grpc.controller.spec.ts b/src/modules/user/tests/unit/interface/update-user.grpc.controller.spec.ts new file mode 100644 index 0000000..4986616 --- /dev/null +++ b/src/modules/user/tests/unit/interface/update-user.grpc.controller.spec.ts @@ -0,0 +1,116 @@ +import { IdResponse } from '@mobicoop/ddd-library'; +import { RpcExceptionCode } from '@mobicoop/ddd-library'; +import { + EmailAlreadyExistsException, + PhoneAlreadyExistsException, +} from '@modules/user/core/domain/user.errors'; +import { UpdateUserRequestDto } from '@modules/user/interface/dtos/grpc-controllers/dtos/update-user.request.dto'; +import { UpdateUserGrpcController } from '@modules/user/interface/dtos/grpc-controllers/update-user.grpc.controller'; + +import { CommandBus } from '@nestjs/cqrs'; +import { RpcException } from '@nestjs/microservices'; +import { Test, TestingModule } from '@nestjs/testing'; + +const updateFirstNameUserRequest: UpdateUserRequestDto = { + id: 'c97b1783-76cf-4840-b298-b90b13c58894', + firstName: 'Johnny', +}; + +const updateEmailUserRequest: UpdateUserRequestDto = { + id: 'c97b1783-76cf-4840-b298-b90b13c58894', + email: 'john.doe@already.exists.email.com', +}; + +const updatePhoneUserRequest: UpdateUserRequestDto = { + id: 'c97b1783-76cf-4840-b298-b90b13c58894', + phone: '+33611223344', +}; + +const mockCommandBus = { + execute: jest + .fn() + .mockImplementationOnce(() => 'c97b1783-76cf-4840-b298-b90b13c58894') + .mockImplementationOnce(() => { + throw new EmailAlreadyExistsException(); + }) + .mockImplementationOnce(() => { + throw new PhoneAlreadyExistsException(); + }) + .mockImplementationOnce(() => { + throw new Error(); + }), +}; + +describe('Update User Grpc Controller', () => { + let updateUserGrpcController: UpdateUserGrpcController; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: CommandBus, + useValue: mockCommandBus, + }, + UpdateUserGrpcController, + ], + }).compile(); + + updateUserGrpcController = module.get( + UpdateUserGrpcController, + ); + }); + + afterEach(async () => { + jest.clearAllMocks(); + }); + + it('should be defined', () => { + expect(updateUserGrpcController).toBeDefined(); + }); + + it('should update a user', async () => { + jest.spyOn(mockCommandBus, 'execute'); + const result: IdResponse = await updateUserGrpcController.updateUser( + updateFirstNameUserRequest, + ); + expect(result).toBeInstanceOf(IdResponse); + expect(result.id).toBe('c97b1783-76cf-4840-b298-b90b13c58894'); + expect(mockCommandBus.execute).toHaveBeenCalledTimes(1); + }); + + it('should throw a dedicated RpcException if email already exists', async () => { + jest.spyOn(mockCommandBus, 'execute'); + expect.assertions(3); + try { + await updateUserGrpcController.updateUser(updateEmailUserRequest); + } catch (e: any) { + expect(e).toBeInstanceOf(RpcException); + expect(e.error.code).toBe(RpcExceptionCode.ALREADY_EXISTS); + } + expect(mockCommandBus.execute).toHaveBeenCalledTimes(1); + }); + + it('should throw a dedicated RpcException if phone already exists', async () => { + jest.spyOn(mockCommandBus, 'execute'); + expect.assertions(3); + try { + await updateUserGrpcController.updateUser(updatePhoneUserRequest); + } catch (e: any) { + expect(e).toBeInstanceOf(RpcException); + expect(e.error.code).toBe(RpcExceptionCode.ALREADY_EXISTS); + } + expect(mockCommandBus.execute).toHaveBeenCalledTimes(1); + }); + + it('should throw a generic RpcException', async () => { + jest.spyOn(mockCommandBus, 'execute'); + expect.assertions(3); + try { + await updateUserGrpcController.updateUser(updateFirstNameUserRequest); + } catch (e: any) { + expect(e).toBeInstanceOf(RpcException); + expect(e.error.code).toBe(RpcExceptionCode.UNKNOWN); + } + expect(mockCommandBus.execute).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/modules/user/tests/unit/message-publisher.spec.ts b/src/modules/user/tests/unit/message-publisher.spec.ts deleted file mode 100644 index c1877e3..0000000 --- a/src/modules/user/tests/unit/message-publisher.spec.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { MessagePublisher } from '../../adapters/secondaries/message-publisher'; -import { MESSAGE_BROKER_PUBLISHER } from '../../../../app.constants'; - -const mockMessageBrokerPublisher = { - publish: jest.fn().mockImplementation(), -}; - -describe('Messager', () => { - let messagePublisher: MessagePublisher; - - beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ - imports: [], - providers: [ - MessagePublisher, - { - provide: MESSAGE_BROKER_PUBLISHER, - useValue: mockMessageBrokerPublisher, - }, - ], - }).compile(); - - messagePublisher = module.get(MessagePublisher); - }); - - it('should be defined', () => { - expect(messagePublisher).toBeDefined(); - }); - - it('should publish a message', async () => { - jest.spyOn(mockMessageBrokerPublisher, 'publish'); - messagePublisher.publish('user.create.info', 'my-test'); - expect(mockMessageBrokerPublisher.publish).toHaveBeenCalledTimes(1); - }); -}); diff --git a/src/modules/user/tests/unit/update-user.usecase.spec.ts b/src/modules/user/tests/unit/update-user.usecase.spec.ts deleted file mode 100644 index a7a89a7..0000000 --- a/src/modules/user/tests/unit/update-user.usecase.spec.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { classes } from '@automapper/classes'; -import { AutomapperModule } from '@automapper/nestjs'; -import { Test, TestingModule } from '@nestjs/testing'; -import { UsersRepository } from '../../adapters/secondaries/users.repository'; -import { UpdateUserCommand } from '../../commands/update-user.command'; -import { UpdateUserRequest } from '../../domain/dtos/update-user.request'; -import { User } from '../../domain/entities/user'; -import { UpdateUserUseCase } from '../../domain/usecases/update-user.usecase'; -import { UserProfile } from '../../mappers/user.profile'; -import { MESSAGE_PUBLISHER } from '../../../../app.constants'; - -const originalUser: User = new User(); -originalUser.uuid = 'bb281075-1b98-4456-89d6-c643d3044a91'; -originalUser.lastName = 'Doe'; - -const updateUserRequest: UpdateUserRequest = { - uuid: 'bb281075-1b98-4456-89d6-c643d3044a91', - lastName: 'Dane', -}; - -const updateUserCommand: UpdateUserCommand = new UpdateUserCommand( - updateUserRequest, -); - -const mockUsersRepository = { - update: jest - .fn() - .mockImplementationOnce((uuid: string, params: any) => { - originalUser.lastName = params.lastName; - - return Promise.resolve(originalUser); - }) - .mockImplementation(() => { - throw new Error('Error'); - }), -}; - -const mockMessager = { - publish: jest.fn().mockImplementation(), -}; - -describe('UpdateUserUseCase', () => { - let updateUserUseCase: UpdateUserUseCase; - - beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ - imports: [AutomapperModule.forRoot({ strategyInitializer: classes() })], - - providers: [ - { - provide: UsersRepository, - useValue: mockUsersRepository, - }, - UpdateUserUseCase, - UserProfile, - { - provide: MESSAGE_PUBLISHER, - useValue: mockMessager, - }, - ], - }).compile(); - - updateUserUseCase = module.get(UpdateUserUseCase); - }); - - it('should be defined', () => { - expect(updateUserUseCase).toBeDefined(); - }); - - describe('execute', () => { - it('should update a user', async () => { - const updatedUser: User = await updateUserUseCase.execute( - updateUserCommand, - ); - - expect(updatedUser.lastName).toBe(updateUserRequest.lastName); - }); - it('should throw an error if user does not exist', async () => { - await expect( - updateUserUseCase.execute(updateUserCommand), - ).rejects.toBeInstanceOf(Error); - }); - }); -}); diff --git a/src/modules/user/tests/unit/user.mapper.spec.ts b/src/modules/user/tests/unit/user.mapper.spec.ts new file mode 100644 index 0000000..d4e3217 --- /dev/null +++ b/src/modules/user/tests/unit/user.mapper.spec.ts @@ -0,0 +1,57 @@ +import { UserEntity } from '@modules/user/core/domain/user.entity'; +import { UserModel } from '@modules/user/infrastructure/user.repository'; +import { UserResponseDto } from '@modules/user/interface/dtos/user.response.dto'; +import { UserMapper } from '@modules/user/user.mapper'; +import { Test } from '@nestjs/testing'; + +const now = new Date('2023-06-21 06:00:00'); +const userEntity: 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 userModel: UserModel = { + uuid: 'c160cf8c-f057-4962-841f-3ad68346df44', + firstName: 'John', + lastName: 'Doe', + email: 'john.doe@email.com', + phone: '+33611223344', + createdAt: now, + updatedAt: now, +}; + +describe('User Mapper', () => { + let userMapper: UserMapper; + + beforeAll(async () => { + const module = await Test.createTestingModule({ + providers: [UserMapper], + }).compile(); + userMapper = module.get(UserMapper); + }); + + it('should be defined', () => { + expect(userMapper).toBeDefined(); + }); + + it('should map domain entity to persistence data', async () => { + const mapped: UserModel = userMapper.toPersistence(userEntity); + expect(mapped.lastName).toBe('Doe'); + }); + + it('should map persisted data to domain entity', async () => { + const mapped: UserEntity = userMapper.toDomain(userModel); + expect(mapped.getProps().firstName).toBe('John'); + }); + + it('should map domain entity to response', async () => { + const mapped: UserResponseDto = userMapper.toResponse(userEntity); + expect(mapped.id).toBe('c160cf8c-f057-4962-841f-3ad68346df44'); + }); +}); diff --git a/src/modules/user/user.di-tokens.ts b/src/modules/user/user.di-tokens.ts new file mode 100644 index 0000000..815cfdb --- /dev/null +++ b/src/modules/user/user.di-tokens.ts @@ -0,0 +1,2 @@ +export const USER_MESSAGE_PUBLISHER = Symbol('USER_MESSAGE_PUBLISHER'); +export const USER_REPOSITORY = Symbol('USER_REPOSITORY'); diff --git a/src/modules/user/user.mapper.ts b/src/modules/user/user.mapper.ts new file mode 100644 index 0000000..b8034f4 --- /dev/null +++ b/src/modules/user/user.mapper.ts @@ -0,0 +1,64 @@ +import { Mapper } from '@mobicoop/ddd-library'; +import { Injectable } from '@nestjs/common'; +import { UserEntity } from './core/domain/user.entity'; +import { UserModel } from './infrastructure/user.repository'; +import { UserResponseDto } from './interface/dtos/user.response.dto'; + +/** + * Mapper constructs objects that are used in different layers: + * Record is an object that is stored in a database, + * Entity is an object that is used in application domain layer, + * and a ResponseDTO is an object returned to a user (usually as json). + */ + +@Injectable() +export class UserMapper + implements Mapper +{ + toPersistence = (entity: UserEntity): UserModel => { + const copy = entity.getProps(); + const record: UserModel = { + uuid: copy.id, + firstName: copy.firstName, + lastName: copy.lastName, + email: copy.email, + phone: copy.phone, + createdAt: copy.createdAt, + updatedAt: copy.updatedAt, + }; + return record; + }; + + toDomain = (record: UserModel): UserEntity => { + const entity = new UserEntity({ + id: record.uuid, + createdAt: new Date(record.createdAt), + updatedAt: new Date(record.updatedAt), + props: { + firstName: record.firstName, + lastName: record.lastName, + email: record.email, + phone: record.phone, + }, + }); + return entity; + }; + + toResponse = (entity: UserEntity): UserResponseDto => { + const props = entity.getProps(); + const response = new UserResponseDto(entity); + response.firstName = props.firstName; + response.lastName = props.lastName; + response.email = props.email; + response.phone = props.phone; + return response; + }; + + /* ^ Data returned to the user is whitelisted to avoid leaks. + If a new property is added, like password or a + credit card number, it won't be returned + unless you specifically allow this. + (avoid blacklisting, which will return everything + but blacklisted items, which can lead to a data leak). + */ +} diff --git a/src/utils/pipes/rpc.validation-pipe.ts b/src/utils/pipes/rpc.validation-pipe.ts deleted file mode 100644 index f2b8c19..0000000 --- a/src/utils/pipes/rpc.validation-pipe.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Injectable, ValidationPipe } from '@nestjs/common'; -import { RpcException } from '@nestjs/microservices'; - -@Injectable() -export class RpcValidationPipe extends ValidationPipe { - createExceptionFactory() { - return (validationErrors = []) => { - return new RpcException({ - code: 3, - message: this.flattenValidationErrors(validationErrors), - }); - }; - } -} diff --git a/src/utils/tests/unit/rpc-validation-pipe.usecase.spec.ts b/src/utils/tests/unit/rpc-validation-pipe.usecase.spec.ts deleted file mode 100644 index b00bf86..0000000 --- a/src/utils/tests/unit/rpc-validation-pipe.usecase.spec.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ArgumentMetadata } from '@nestjs/common'; -import { UpdateUserRequest } from '../../../modules/user/domain/dtos/update-user.request'; -import { RpcValidationPipe } from '../../pipes/rpc.validation-pipe'; - -describe('RpcValidationPipe', () => { - it('should not validate request', async () => { - const target: RpcValidationPipe = new RpcValidationPipe({ - whitelist: true, - forbidUnknownValues: false, - }); - const metadata: ArgumentMetadata = { - type: 'body', - metatype: UpdateUserRequest, - data: '', - }; - await target.transform({}, metadata).catch((err) => { - expect(err.message).toEqual('Rpc Exception'); - }); - }); -}); diff --git a/tsconfig.json b/tsconfig.json index adb614c..0e31118 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,6 +16,10 @@ "noImplicitAny": false, "strictBindCallApply": false, "forceConsistentCasingInFileNames": false, - "noFallthroughCasesInSwitch": false + "noFallthroughCasesInSwitch": false, + "paths": { + "@modules/*": ["src/modules/*"], + "@src/*": ["src/*"] + } } } From 52fd0b952bea05181e2c29db2c642d67e7f76d3c Mon Sep 17 00:00:00 2001 From: sbriat Date: Fri, 21 Jul 2023 14:22:13 +0200 Subject: [PATCH 2/9] user update --- .../adapters/primaries/user.controller.ts | 0 .../adapters/primaries/user.presenter.ts | 0 .../adapters/primaries/user.proto | 0 .../adapters/secondaries/message-publisher.ts | 0 .../adapters/secondaries/users.repository.ts | 0 .../commands/create-user.command.ts | 0 .../commands/delete-user.command.ts | 0 .../commands/update-user.command.ts | 0 .../domain/dtos/create-user.request.ts | 0 .../domain/dtos/find-all-users.request.ts | 0 .../domain/dtos/find-user-by-uuid.request.ts | 0 .../domain/dtos/update-user.request.ts | 0 .../user/old => .old}/domain/entities/user.ts | 0 .../domain/usecases/create-user.usecase.ts | 0 .../domain/usecases/delete-user.usecase.ts | 0 .../domain/usecases/find-all-users.usecase.ts | 0 .../usecases/find-user-by-uuid.usecase.ts | 0 .../domain/usecases/update-user.usecase.ts | 0 .../user/old => .old}/mappers/user.profile.ts | 0 .../queries/find-all-users.query.ts | 0 .../queries/find-user-by-uuid.query.ts | 0 .../tests/unit/find-all-users.usecase.spec.ts | 0 .../unit/find-user-by-uuid.usecase.spec.ts | 0 package-lock.json | 24 +++- package.json | 1 + src/app.module.ts | 2 + .../create-user/create-user.service.ts | 24 +++- .../update-user/update-user.service.ts | 10 +- src/modules/user/core/domain/user.entity.ts | 8 +- src/modules/user/core/domain/user.types.ts | 24 ++-- .../create-user.grpc.controller.ts | 12 +- .../dtos/create-user.request.dto.ts | 0 .../dtos/update-user.request.dto.ts | 0 .../update-user.grpc.controller.ts | 0 .../{dtos => }/grpc-controllers/user.proto | 14 +- .../unit/core/create-user.service.spec.ts | 34 ++++- .../unit/core/update-user.service.spec.ts | 126 ++++++++++++++++++ .../create-user.grpc.controller.spec.ts | 40 +++++- .../update-user.grpc.controller.spec.ts | 4 +- src/modules/user/user.module.ts | 103 +++++++------- 40 files changed, 328 insertions(+), 98 deletions(-) rename {src/modules/user/old => .old}/adapters/primaries/user.controller.ts (100%) rename {src/modules/user/old => .old}/adapters/primaries/user.presenter.ts (100%) rename {src/modules/user/old => .old}/adapters/primaries/user.proto (100%) rename {src/modules/user/old => .old}/adapters/secondaries/message-publisher.ts (100%) rename {src/modules/user/old => .old}/adapters/secondaries/users.repository.ts (100%) rename {src/modules/user/old => .old}/commands/create-user.command.ts (100%) rename {src/modules/user/old => .old}/commands/delete-user.command.ts (100%) rename {src/modules/user/old => .old}/commands/update-user.command.ts (100%) rename {src/modules/user/old => .old}/domain/dtos/create-user.request.ts (100%) rename {src/modules/user/old => .old}/domain/dtos/find-all-users.request.ts (100%) rename {src/modules/user/old => .old}/domain/dtos/find-user-by-uuid.request.ts (100%) rename {src/modules/user/old => .old}/domain/dtos/update-user.request.ts (100%) rename {src/modules/user/old => .old}/domain/entities/user.ts (100%) rename {src/modules/user/old => .old}/domain/usecases/create-user.usecase.ts (100%) rename {src/modules/user/old => .old}/domain/usecases/delete-user.usecase.ts (100%) rename {src/modules/user/old => .old}/domain/usecases/find-all-users.usecase.ts (100%) rename {src/modules/user/old => .old}/domain/usecases/find-user-by-uuid.usecase.ts (100%) rename {src/modules/user/old => .old}/domain/usecases/update-user.usecase.ts (100%) rename {src/modules/user/old => .old}/mappers/user.profile.ts (100%) rename {src/modules/user/old => .old}/queries/find-all-users.query.ts (100%) rename {src/modules/user/old => .old}/queries/find-user-by-uuid.query.ts (100%) rename {src/modules/user/old => .old}/tests/unit/find-all-users.usecase.spec.ts (100%) rename {src/modules/user/old => .old}/tests/unit/find-user-by-uuid.usecase.spec.ts (100%) rename src/modules/user/interface/{dtos => }/grpc-controllers/create-user.grpc.controller.ts (80%) rename src/modules/user/interface/{dtos => }/grpc-controllers/dtos/create-user.request.dto.ts (100%) rename src/modules/user/interface/{dtos => }/grpc-controllers/dtos/update-user.request.dto.ts (100%) rename src/modules/user/interface/{dtos => }/grpc-controllers/update-user.grpc.controller.ts (100%) rename src/modules/user/interface/{dtos => }/grpc-controllers/user.proto (63%) create mode 100644 src/modules/user/tests/unit/core/update-user.service.spec.ts diff --git a/src/modules/user/old/adapters/primaries/user.controller.ts b/.old/adapters/primaries/user.controller.ts similarity index 100% rename from src/modules/user/old/adapters/primaries/user.controller.ts rename to .old/adapters/primaries/user.controller.ts diff --git a/src/modules/user/old/adapters/primaries/user.presenter.ts b/.old/adapters/primaries/user.presenter.ts similarity index 100% rename from src/modules/user/old/adapters/primaries/user.presenter.ts rename to .old/adapters/primaries/user.presenter.ts diff --git a/src/modules/user/old/adapters/primaries/user.proto b/.old/adapters/primaries/user.proto similarity index 100% rename from src/modules/user/old/adapters/primaries/user.proto rename to .old/adapters/primaries/user.proto diff --git a/src/modules/user/old/adapters/secondaries/message-publisher.ts b/.old/adapters/secondaries/message-publisher.ts similarity index 100% rename from src/modules/user/old/adapters/secondaries/message-publisher.ts rename to .old/adapters/secondaries/message-publisher.ts diff --git a/src/modules/user/old/adapters/secondaries/users.repository.ts b/.old/adapters/secondaries/users.repository.ts similarity index 100% rename from src/modules/user/old/adapters/secondaries/users.repository.ts rename to .old/adapters/secondaries/users.repository.ts diff --git a/src/modules/user/old/commands/create-user.command.ts b/.old/commands/create-user.command.ts similarity index 100% rename from src/modules/user/old/commands/create-user.command.ts rename to .old/commands/create-user.command.ts diff --git a/src/modules/user/old/commands/delete-user.command.ts b/.old/commands/delete-user.command.ts similarity index 100% rename from src/modules/user/old/commands/delete-user.command.ts rename to .old/commands/delete-user.command.ts diff --git a/src/modules/user/old/commands/update-user.command.ts b/.old/commands/update-user.command.ts similarity index 100% rename from src/modules/user/old/commands/update-user.command.ts rename to .old/commands/update-user.command.ts diff --git a/src/modules/user/old/domain/dtos/create-user.request.ts b/.old/domain/dtos/create-user.request.ts similarity index 100% rename from src/modules/user/old/domain/dtos/create-user.request.ts rename to .old/domain/dtos/create-user.request.ts diff --git a/src/modules/user/old/domain/dtos/find-all-users.request.ts b/.old/domain/dtos/find-all-users.request.ts similarity index 100% rename from src/modules/user/old/domain/dtos/find-all-users.request.ts rename to .old/domain/dtos/find-all-users.request.ts diff --git a/src/modules/user/old/domain/dtos/find-user-by-uuid.request.ts b/.old/domain/dtos/find-user-by-uuid.request.ts similarity index 100% rename from src/modules/user/old/domain/dtos/find-user-by-uuid.request.ts rename to .old/domain/dtos/find-user-by-uuid.request.ts diff --git a/src/modules/user/old/domain/dtos/update-user.request.ts b/.old/domain/dtos/update-user.request.ts similarity index 100% rename from src/modules/user/old/domain/dtos/update-user.request.ts rename to .old/domain/dtos/update-user.request.ts diff --git a/src/modules/user/old/domain/entities/user.ts b/.old/domain/entities/user.ts similarity index 100% rename from src/modules/user/old/domain/entities/user.ts rename to .old/domain/entities/user.ts diff --git a/src/modules/user/old/domain/usecases/create-user.usecase.ts b/.old/domain/usecases/create-user.usecase.ts similarity index 100% rename from src/modules/user/old/domain/usecases/create-user.usecase.ts rename to .old/domain/usecases/create-user.usecase.ts diff --git a/src/modules/user/old/domain/usecases/delete-user.usecase.ts b/.old/domain/usecases/delete-user.usecase.ts similarity index 100% rename from src/modules/user/old/domain/usecases/delete-user.usecase.ts rename to .old/domain/usecases/delete-user.usecase.ts diff --git a/src/modules/user/old/domain/usecases/find-all-users.usecase.ts b/.old/domain/usecases/find-all-users.usecase.ts similarity index 100% rename from src/modules/user/old/domain/usecases/find-all-users.usecase.ts rename to .old/domain/usecases/find-all-users.usecase.ts diff --git a/src/modules/user/old/domain/usecases/find-user-by-uuid.usecase.ts b/.old/domain/usecases/find-user-by-uuid.usecase.ts similarity index 100% rename from src/modules/user/old/domain/usecases/find-user-by-uuid.usecase.ts rename to .old/domain/usecases/find-user-by-uuid.usecase.ts diff --git a/src/modules/user/old/domain/usecases/update-user.usecase.ts b/.old/domain/usecases/update-user.usecase.ts similarity index 100% rename from src/modules/user/old/domain/usecases/update-user.usecase.ts rename to .old/domain/usecases/update-user.usecase.ts diff --git a/src/modules/user/old/mappers/user.profile.ts b/.old/mappers/user.profile.ts similarity index 100% rename from src/modules/user/old/mappers/user.profile.ts rename to .old/mappers/user.profile.ts diff --git a/src/modules/user/old/queries/find-all-users.query.ts b/.old/queries/find-all-users.query.ts similarity index 100% rename from src/modules/user/old/queries/find-all-users.query.ts rename to .old/queries/find-all-users.query.ts diff --git a/src/modules/user/old/queries/find-user-by-uuid.query.ts b/.old/queries/find-user-by-uuid.query.ts similarity index 100% rename from src/modules/user/old/queries/find-user-by-uuid.query.ts rename to .old/queries/find-user-by-uuid.query.ts diff --git a/src/modules/user/old/tests/unit/find-all-users.usecase.spec.ts b/.old/tests/unit/find-all-users.usecase.spec.ts similarity index 100% rename from src/modules/user/old/tests/unit/find-all-users.usecase.spec.ts rename to .old/tests/unit/find-all-users.usecase.spec.ts diff --git a/src/modules/user/old/tests/unit/find-user-by-uuid.usecase.spec.ts b/.old/tests/unit/find-user-by-uuid.usecase.spec.ts similarity index 100% rename from src/modules/user/old/tests/unit/find-user-by-uuid.usecase.spec.ts rename to .old/tests/unit/find-user-by-uuid.usecase.spec.ts diff --git a/package-lock.json b/package-lock.json index 604bacb..d9cf986 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "@nestjs/config": "^2.2.0", "@nestjs/core": "^9.0.0", "@nestjs/cqrs": "^9.0.1", + "@nestjs/event-emitter": "^2.0.0", "@nestjs/microservices": "^9.2.1", "@nestjs/platform-express": "^9.0.0", "@nestjs/terminus": "^9.2.2", @@ -1937,6 +1938,19 @@ "@nestjs/common": "^9.4.2" } }, + "node_modules/@mobicoop/ddd-library/node_modules/@nestjs/event-emitter": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@nestjs/event-emitter/-/event-emitter-1.4.2.tgz", + "integrity": "sha512-5mskPMS4KVH6LghC+NynfdmGiMCOOv9CdgVpuWGipLrJECv5KWc7vaW5o/9BYrcqPkN7Ted6CJ+O4AfsTiRlgw==", + "dependencies": { + "eventemitter2": "6.4.9" + }, + "peerDependencies": { + "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0", + "@nestjs/core": "^7.0.0 || ^8.0.0 || ^9.0.0", + "reflect-metadata": "^0.1.12" + } + }, "node_modules/@mobicoop/health-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@mobicoop/health-module/-/health-module-2.0.0.tgz", @@ -2206,15 +2220,15 @@ } }, "node_modules/@nestjs/event-emitter": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@nestjs/event-emitter/-/event-emitter-1.4.2.tgz", - "integrity": "sha512-5mskPMS4KVH6LghC+NynfdmGiMCOOv9CdgVpuWGipLrJECv5KWc7vaW5o/9BYrcqPkN7Ted6CJ+O4AfsTiRlgw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@nestjs/event-emitter/-/event-emitter-2.0.0.tgz", + "integrity": "sha512-fZRv3+PmqXcbqCDRXRWhKDa+v3gmPUq4x5sQE5reVlDtEaCoAXwtGrtNswPtqd0msjyo8OWZF9k1sFjeRL6Xag==", "dependencies": { "eventemitter2": "6.4.9" }, "peerDependencies": { - "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0", - "@nestjs/core": "^7.0.0 || ^8.0.0 || ^9.0.0", + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", "reflect-metadata": "^0.1.12" } }, diff --git a/package.json b/package.json index 5099135..b6893b0 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "@nestjs/config": "^2.2.0", "@nestjs/core": "^9.0.0", "@nestjs/cqrs": "^9.0.1", + "@nestjs/event-emitter": "^2.0.0", "@nestjs/microservices": "^9.2.1", "@nestjs/platform-express": "^9.0.0", "@nestjs/terminus": "^9.2.2", diff --git a/src/app.module.ts b/src/app.module.ts index 9e7c1bc..5ecd4ee 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -14,10 +14,12 @@ import { MessagerModule } from './modules/messager/messager.module'; import { USER_REPOSITORY } from './modules/user/user.di-tokens'; import { MESSAGE_PUBLISHER } from './modules/messager/messager.di-tokens'; import { MessagePublisherPort } from '@mobicoop/ddd-library'; +import { EventEmitterModule } from '@nestjs/event-emitter'; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true }), + EventEmitterModule.forRoot(), ConfigurationModule.forRootAsync({ imports: [ConfigModule], inject: [ConfigService], diff --git a/src/modules/user/core/application/commands/create-user/create-user.service.ts b/src/modules/user/core/application/commands/create-user/create-user.service.ts index 077ca82..e564340 100644 --- a/src/modules/user/core/application/commands/create-user/create-user.service.ts +++ b/src/modules/user/core/application/commands/create-user/create-user.service.ts @@ -1,11 +1,19 @@ import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'; import { Inject } from '@nestjs/common'; -import { AggregateID, ConflictException } from '@mobicoop/ddd-library'; +import { + AggregateID, + ConflictException, + UniqueConstraintException, +} from '@mobicoop/ddd-library'; import { CreateUserCommand } from './create-user.command'; import { USER_REPOSITORY } from '@modules/user/user.di-tokens'; import { UserRepositoryPort } from '../../ports/user.repository.port'; import { UserEntity } from '../../../domain/user.entity'; -import { UserAlreadyExistsException } from '../../../domain/user.errors'; +import { + EmailAlreadyExistsException, + PhoneAlreadyExistsException, + UserAlreadyExistsException, +} from '../../../domain/user.errors'; @CommandHandler(CreateUserCommand) export class CreateUserService implements ICommandHandler { @@ -29,6 +37,18 @@ export class CreateUserService implements ICommandHandler { if (error instanceof ConflictException) { throw new UserAlreadyExistsException(error); } + if ( + error instanceof UniqueConstraintException && + error.message.includes('email') + ) { + throw new EmailAlreadyExistsException(error); + } + if ( + error instanceof UniqueConstraintException && + error.message.includes('phone') + ) { + throw new PhoneAlreadyExistsException(error); + } throw error; } } diff --git a/src/modules/user/core/application/commands/update-user/update-user.service.ts b/src/modules/user/core/application/commands/update-user/update-user.service.ts index 78d6241..10096cf 100644 --- a/src/modules/user/core/application/commands/update-user/update-user.service.ts +++ b/src/modules/user/core/application/commands/update-user/update-user.service.ts @@ -1,10 +1,6 @@ import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'; import { Inject } from '@nestjs/common'; -import { - AggregateID, - ConflictException, - UniqueConstraintException, -} from '@mobicoop/ddd-library'; +import { AggregateID, UniqueConstraintException } from '@mobicoop/ddd-library'; import { USER_REPOSITORY } from '@modules/user/user.di-tokens'; import { UserRepositoryPort } from '../../ports/user.repository.port'; import { UserEntity } from '../../../domain/user.entity'; @@ -12,7 +8,6 @@ import { UpdateUserCommand } from './update-user.command'; import { EmailAlreadyExistsException, PhoneAlreadyExistsException, - UserAlreadyExistsException, } from '@modules/user/core/domain/user.errors'; @CommandHandler(UpdateUserCommand) @@ -36,9 +31,6 @@ export class UpdateUserService implements ICommandHandler { await this.userRepository.update(user.id, user); return user.id; } catch (error: any) { - if (error instanceof ConflictException) { - throw new UserAlreadyExistsException(error); - } if ( error instanceof UniqueConstraintException && error.message.includes('email') diff --git a/src/modules/user/core/domain/user.entity.ts b/src/modules/user/core/domain/user.entity.ts index 8ec3605..0bb810f 100644 --- a/src/modules/user/core/domain/user.entity.ts +++ b/src/modules/user/core/domain/user.entity.ts @@ -25,10 +25,10 @@ export class UserEntity extends AggregateRoot { }; update(props: UpdateUserProps): void { - this.props.firstName = props.firstName; - this.props.lastName = props.lastName; - this.props.email = props.email; - this.props.phone = props.phone; + this.props.firstName = props.firstName ?? this.props.firstName; + this.props.lastName = props.lastName ?? this.props.lastName; + this.props.email = props.email ?? this.props.email; + this.props.phone = props.phone ?? this.props.phone; this.addEvent( new UserUpdatedDomainEvent({ aggregateId: this._id, diff --git a/src/modules/user/core/domain/user.types.ts b/src/modules/user/core/domain/user.types.ts index d2c8782..1cf4f95 100644 --- a/src/modules/user/core/domain/user.types.ts +++ b/src/modules/user/core/domain/user.types.ts @@ -1,22 +1,22 @@ // All properties that a User has export interface UserProps { - firstName: string; - lastName: string; - email: string; - phone: string; + firstName?: string; + lastName?: string; + email?: string; + phone?: string; } // Properties that are needed for a User creation export interface CreateUserProps { - firstName: string; - lastName: string; - email: string; - phone: string; + firstName?: string; + lastName?: string; + email?: string; + phone?: string; } export interface UpdateUserProps { - firstName: string; - lastName: string; - email: string; - phone: string; + firstName?: string; + lastName?: string; + email?: string; + phone?: string; } diff --git a/src/modules/user/interface/dtos/grpc-controllers/create-user.grpc.controller.ts b/src/modules/user/interface/grpc-controllers/create-user.grpc.controller.ts similarity index 80% rename from src/modules/user/interface/dtos/grpc-controllers/create-user.grpc.controller.ts rename to src/modules/user/interface/grpc-controllers/create-user.grpc.controller.ts index e234c5b..15ce502 100644 --- a/src/modules/user/interface/dtos/grpc-controllers/create-user.grpc.controller.ts +++ b/src/modules/user/interface/grpc-controllers/create-user.grpc.controller.ts @@ -7,7 +7,11 @@ import { RpcExceptionCode } from '@mobicoop/ddd-library'; import { RpcValidationPipe } from '@mobicoop/ddd-library'; import { CreateUserRequestDto } from './dtos/create-user.request.dto'; import { CreateUserCommand } from '@modules/user/core/application/commands/create-user/create-user.command'; -import { UserAlreadyExistsException } from '@modules/user/core/domain/user.errors'; +import { + EmailAlreadyExistsException, + PhoneAlreadyExistsException, + UserAlreadyExistsException, +} from '@modules/user/core/domain/user.errors'; @UsePipes( new RpcValidationPipe({ @@ -27,7 +31,11 @@ export class CreateUserGrpcController { ); return new IdResponse(aggregateID); } catch (error: any) { - if (error instanceof UserAlreadyExistsException) + if ( + error instanceof UserAlreadyExistsException || + error instanceof EmailAlreadyExistsException || + error instanceof PhoneAlreadyExistsException + ) throw new RpcException({ code: RpcExceptionCode.ALREADY_EXISTS, message: error.message, diff --git a/src/modules/user/interface/dtos/grpc-controllers/dtos/create-user.request.dto.ts b/src/modules/user/interface/grpc-controllers/dtos/create-user.request.dto.ts similarity index 100% rename from src/modules/user/interface/dtos/grpc-controllers/dtos/create-user.request.dto.ts rename to src/modules/user/interface/grpc-controllers/dtos/create-user.request.dto.ts diff --git a/src/modules/user/interface/dtos/grpc-controllers/dtos/update-user.request.dto.ts b/src/modules/user/interface/grpc-controllers/dtos/update-user.request.dto.ts similarity index 100% rename from src/modules/user/interface/dtos/grpc-controllers/dtos/update-user.request.dto.ts rename to src/modules/user/interface/grpc-controllers/dtos/update-user.request.dto.ts diff --git a/src/modules/user/interface/dtos/grpc-controllers/update-user.grpc.controller.ts b/src/modules/user/interface/grpc-controllers/update-user.grpc.controller.ts similarity index 100% rename from src/modules/user/interface/dtos/grpc-controllers/update-user.grpc.controller.ts rename to src/modules/user/interface/grpc-controllers/update-user.grpc.controller.ts diff --git a/src/modules/user/interface/dtos/grpc-controllers/user.proto b/src/modules/user/interface/grpc-controllers/user.proto similarity index 63% rename from src/modules/user/interface/dtos/grpc-controllers/user.proto rename to src/modules/user/interface/grpc-controllers/user.proto index cde99ea..075c6e7 100644 --- a/src/modules/user/interface/dtos/grpc-controllers/user.proto +++ b/src/modules/user/interface/grpc-controllers/user.proto @@ -3,19 +3,19 @@ syntax = "proto3"; package user; service UserService { - rpc FindOneByUuid(UserByUuid) returns (User); + rpc FindOneById(UserById) returns (User); rpc FindAll(UserFilter) returns (Users); - rpc Create(User) returns (User); - rpc Update(User) returns (User); - rpc Delete(UserByUuid) returns (Empty); + rpc Create(User) returns (UserById); + rpc Update(User) returns (UserById); + rpc Delete(UserById) returns (Empty); } -message UserByUuid { - string uuid = 1; +message UserById { + string id = 1; } message User { - string uuid = 1; + string id = 1; string firstName = 2; string lastName = 3; string email = 4; diff --git a/src/modules/user/tests/unit/core/create-user.service.spec.ts b/src/modules/user/tests/unit/core/create-user.service.spec.ts index 32bb093..fbd1c60 100644 --- a/src/modules/user/tests/unit/core/create-user.service.spec.ts +++ b/src/modules/user/tests/unit/core/create-user.service.spec.ts @@ -1,12 +1,16 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { AggregateID } from '@mobicoop/ddd-library'; +import { AggregateID, UniqueConstraintException } from '@mobicoop/ddd-library'; import { ConflictException } from '@mobicoop/ddd-library'; -import { CreateUserRequestDto } from '@modules/user/interface/dtos/grpc-controllers/dtos/create-user.request.dto'; +import { CreateUserRequestDto } from '@modules/user/interface/grpc-controllers/dtos/create-user.request.dto'; import { CreateUserService } from '@modules/user/core/application/commands/create-user/create-user.service'; import { USER_REPOSITORY } from '@modules/user/user.di-tokens'; import { UserEntity } from '@modules/user/core/domain/user.entity'; import { CreateUserCommand } from '@modules/user/core/application/commands/create-user/create-user.command'; -import { UserAlreadyExistsException } from '@modules/user/core/domain/user.errors'; +import { + EmailAlreadyExistsException, + PhoneAlreadyExistsException, + UserAlreadyExistsException, +} from '@modules/user/core/domain/user.errors'; const createUserRequest: CreateUserRequestDto = { firstName: 'John', @@ -23,7 +27,13 @@ const mockUserRepository = { throw new Error(); }) .mockImplementationOnce(() => { - throw new ConflictException('already exists'); + throw new ConflictException('User already exists'); + }) + .mockImplementationOnce(() => { + throw new UniqueConstraintException('email already exists'); + }) + .mockImplementationOnce(() => { + throw new UniqueConstraintException('phone already exists'); }), }; @@ -75,5 +85,21 @@ describe('create-user.service', () => { createUserService.execute(createUserCommand), ).rejects.toBeInstanceOf(UserAlreadyExistsException); }); + it('should throw an exception if Email already exists', async () => { + UserEntity.create = jest.fn().mockReturnValue({ + id: '047a6ecf-23d4-4d3e-877c-3225d560a8da', + }); + await expect( + createUserService.execute(createUserCommand), + ).rejects.toBeInstanceOf(EmailAlreadyExistsException); + }); + it('should throw an exception if Phone already exists', async () => { + UserEntity.create = jest.fn().mockReturnValue({ + id: '047a6ecf-23d4-4d3e-877c-3225d560a8da', + }); + await expect( + createUserService.execute(createUserCommand), + ).rejects.toBeInstanceOf(PhoneAlreadyExistsException); + }); }); }); diff --git a/src/modules/user/tests/unit/core/update-user.service.spec.ts b/src/modules/user/tests/unit/core/update-user.service.spec.ts new file mode 100644 index 0000000..797f850 --- /dev/null +++ b/src/modules/user/tests/unit/core/update-user.service.spec.ts @@ -0,0 +1,126 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { + AggregateID, + NotFoundException, + UniqueConstraintException, +} from '@mobicoop/ddd-library'; +import { USER_REPOSITORY } from '@modules/user/user.di-tokens'; +import { UserEntity } from '@modules/user/core/domain/user.entity'; +import { + EmailAlreadyExistsException, + PhoneAlreadyExistsException, +} from '@modules/user/core/domain/user.errors'; +import { UpdateUserRequestDto } from '@modules/user/interface/grpc-controllers/dtos/update-user.request.dto'; +import { UpdateUserService } from '@modules/user/core/application/commands/update-user/update-user.service'; +import { UpdateUserCommand } from '@modules/user/core/application/commands/update-user/update-user.command'; + +const updateFirstNameUserRequest: UpdateUserRequestDto = { + id: 'c97b1783-76cf-4840-b298-b90b13c58894', + firstName: 'Johnny', +}; + +const updateEmailUserRequest: UpdateUserRequestDto = { + id: 'c97b1783-76cf-4840-b298-b90b13c58894', + email: 'john.doe@already.exists.email.com', +}; + +const updatePhoneUserRequest: UpdateUserRequestDto = { + id: 'c97b1783-76cf-4840-b298-b90b13c58894', + phone: '+33611223344', +}; + +const now = new Date(); +const userToUpdate: UserEntity = new UserEntity({ + id: 'c97b1783-76cf-4840-b298-b90b13c58894', + createdAt: now, + updatedAt: now, + props: { + firstName: 'John', + lastName: 'Doe', + email: 'john.doe@email.com', + phone: '+33611223344', + }, +}); + +const mockUserRepository = { + findOneById: jest + .fn() + .mockImplementationOnce(() => { + throw new NotFoundException('Record not found'); + }) + .mockImplementation(() => userToUpdate), + update: jest + .fn() + .mockImplementationOnce(() => 'c97b1783-76cf-4840-b298-b90b13c58894') + .mockImplementationOnce(() => { + throw new UniqueConstraintException('email already exists'); + }) + .mockImplementationOnce(() => { + throw new UniqueConstraintException('phone already exists'); + }) + .mockImplementationOnce(() => { + throw new Error(); + }), +}; + +describe('update-user.service', () => { + let updateUserService: UpdateUserService; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: USER_REPOSITORY, + useValue: mockUserRepository, + }, + UpdateUserService, + ], + }).compile(); + + updateUserService = module.get(UpdateUserService); + }); + + it('should be defined', () => { + expect(updateUserService).toBeDefined(); + }); + + describe('execution', () => { + it('should throw an exception if use is not found', async () => { + const updateUserCommand = new UpdateUserCommand( + updateFirstNameUserRequest, + ); + await expect( + updateUserService.execute(updateUserCommand), + ).rejects.toBeInstanceOf(NotFoundException); + }); + it('should update a user firstName', async () => { + jest.spyOn(userToUpdate, 'update'); + const updateUserCommand = new UpdateUserCommand( + updateFirstNameUserRequest, + ); + const result: AggregateID = await updateUserService.execute( + updateUserCommand, + ); + expect(result).toBe('c97b1783-76cf-4840-b298-b90b13c58894'); + expect(userToUpdate.update).toHaveBeenCalledTimes(1); + }); + it('should throw an exception if Email already exists', async () => { + const updateUserCommand = new UpdateUserCommand(updateEmailUserRequest); + await expect( + updateUserService.execute(updateUserCommand), + ).rejects.toBeInstanceOf(EmailAlreadyExistsException); + }); + it('should throw an exception if Phone already exists', async () => { + const updateUserCommand = new UpdateUserCommand(updatePhoneUserRequest); + await expect( + updateUserService.execute(updateUserCommand), + ).rejects.toBeInstanceOf(PhoneAlreadyExistsException); + }); + it('should throw an error if something bad happens', async () => { + const updateUserCommand = new UpdateUserCommand(updatePhoneUserRequest); + await expect( + updateUserService.execute(updateUserCommand), + ).rejects.toBeInstanceOf(Error); + }); + }); +}); diff --git a/src/modules/user/tests/unit/interface/create-user.grpc.controller.spec.ts b/src/modules/user/tests/unit/interface/create-user.grpc.controller.spec.ts index 3d7acc0..b2df2f5 100644 --- a/src/modules/user/tests/unit/interface/create-user.grpc.controller.spec.ts +++ b/src/modules/user/tests/unit/interface/create-user.grpc.controller.spec.ts @@ -3,9 +3,13 @@ import { RpcExceptionCode } from '@mobicoop/ddd-library'; import { CommandBus } from '@nestjs/cqrs'; import { RpcException } from '@nestjs/microservices'; import { Test, TestingModule } from '@nestjs/testing'; -import { UserAlreadyExistsException } from '@modules/user/core/domain/user.errors'; -import { CreateUserGrpcController } from '@modules/user/interface/dtos/grpc-controllers/create-user.grpc.controller'; -import { CreateUserRequestDto } from '@modules/user/interface/dtos/grpc-controllers/dtos/create-user.request.dto'; +import { + EmailAlreadyExistsException, + PhoneAlreadyExistsException, + UserAlreadyExistsException, +} from '@modules/user/core/domain/user.errors'; +import { CreateUserGrpcController } from '@modules/user/interface/grpc-controllers/create-user.grpc.controller'; +import { CreateUserRequestDto } from '@modules/user/interface/grpc-controllers/dtos/create-user.request.dto'; const createUserRequest: CreateUserRequestDto = { firstName: 'John', @@ -21,6 +25,12 @@ const mockCommandBus = { .mockImplementationOnce(() => { throw new UserAlreadyExistsException(); }) + .mockImplementationOnce(() => { + throw new EmailAlreadyExistsException(); + }) + .mockImplementationOnce(() => { + throw new PhoneAlreadyExistsException(); + }) .mockImplementationOnce(() => { throw new Error(); }), @@ -75,6 +85,30 @@ describe('Create User Grpc Controller', () => { expect(mockCommandBus.execute).toHaveBeenCalledTimes(1); }); + it('should throw a dedicated RpcException if email already exists', async () => { + jest.spyOn(mockCommandBus, 'execute'); + expect.assertions(3); + try { + await createUserGrpcController.create(createUserRequest); + } catch (e: any) { + expect(e).toBeInstanceOf(RpcException); + expect(e.error.code).toBe(RpcExceptionCode.ALREADY_EXISTS); + } + expect(mockCommandBus.execute).toHaveBeenCalledTimes(1); + }); + + it('should throw a dedicated RpcException if phone already exists', async () => { + jest.spyOn(mockCommandBus, 'execute'); + expect.assertions(3); + try { + await createUserGrpcController.create(createUserRequest); + } catch (e: any) { + expect(e).toBeInstanceOf(RpcException); + expect(e.error.code).toBe(RpcExceptionCode.ALREADY_EXISTS); + } + expect(mockCommandBus.execute).toHaveBeenCalledTimes(1); + }); + it('should throw a generic RpcException', async () => { jest.spyOn(mockCommandBus, 'execute'); expect.assertions(3); diff --git a/src/modules/user/tests/unit/interface/update-user.grpc.controller.spec.ts b/src/modules/user/tests/unit/interface/update-user.grpc.controller.spec.ts index 4986616..637a926 100644 --- a/src/modules/user/tests/unit/interface/update-user.grpc.controller.spec.ts +++ b/src/modules/user/tests/unit/interface/update-user.grpc.controller.spec.ts @@ -4,8 +4,8 @@ import { EmailAlreadyExistsException, PhoneAlreadyExistsException, } from '@modules/user/core/domain/user.errors'; -import { UpdateUserRequestDto } from '@modules/user/interface/dtos/grpc-controllers/dtos/update-user.request.dto'; -import { UpdateUserGrpcController } from '@modules/user/interface/dtos/grpc-controllers/update-user.grpc.controller'; +import { UpdateUserRequestDto } from '@modules/user/interface/grpc-controllers/dtos/update-user.request.dto'; +import { UpdateUserGrpcController } from '@modules/user/interface/grpc-controllers/update-user.grpc.controller'; import { CommandBus } from '@nestjs/cqrs'; import { RpcException } from '@nestjs/microservices'; diff --git a/src/modules/user/user.module.ts b/src/modules/user/user.module.ts index 23315ba..15646bf 100644 --- a/src/modules/user/user.module.ts +++ b/src/modules/user/user.module.ts @@ -1,60 +1,67 @@ import { RedisClientOptions } from '@liaoliaots/nestjs-redis'; -import { Module } from '@nestjs/common'; +import { Module, Provider } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { CqrsModule } from '@nestjs/cqrs'; import { redisStore } from 'cache-manager-ioredis-yet'; -import { DatabaseModule } from '../database/database.module'; -import { UserController } from './adapters/primaries/user.controller'; -import { UsersRepository } from './adapters/secondaries/users.repository'; -import { CreateUserUseCase } from './domain/usecases/create-user.usecase'; -import { DeleteUserUseCase } from './domain/usecases/delete-user.usecase'; -import { FindAllUsersUseCase } from './domain/usecases/find-all-users.usecase'; -import { FindUserByUuidUseCase } from './domain/usecases/find-user-by-uuid.usecase'; -import { UpdateUserUseCase } from './domain/usecases/update-user.usecase'; -import { UserProfile } from './mappers/user.profile'; import { CacheModule } from '@nestjs/cache-manager'; import { MessageBrokerPublisher } from '@mobicoop/message-broker-module'; -import { - MESSAGE_BROKER_PUBLISHER, - MESSAGE_PUBLISHER, -} from '../../app.constants'; -import { MessagePublisher } from './adapters/secondaries/message-publisher'; +import { CreateUserGrpcController } from './interface/grpc-controllers/create-user.grpc.controller'; +import { UpdateUserGrpcController } from './interface/grpc-controllers/update-user.grpc.controller'; +import { CreateUserService } from './core/application/commands/create-user/create-user.service'; +import { UpdateUserService } from './core/application/commands/update-user/update-user.service'; +import { USER_MESSAGE_PUBLISHER, USER_REPOSITORY } from './user.di-tokens'; +import { UserRepository } from './infrastructure/user.repository'; +import { UserMapper } from './user.mapper'; +import { PrismaService } from './infrastructure/prisma.service'; + +const imports = [ + CqrsModule, + CacheModule.registerAsync({ + imports: [ConfigModule], + useFactory: async (configService: ConfigService) => ({ + store: await redisStore({ + host: configService.get('REDIS_HOST'), + port: configService.get('REDIS_PORT'), + password: configService.get('REDIS_PASSWORD'), + ttl: configService.get('CACHE_TTL'), + }), + }), + inject: [ConfigService], + }), +]; + +const grpcControllers = [CreateUserGrpcController, UpdateUserGrpcController]; + +const commandHandlers: Provider[] = [CreateUserService, UpdateUserService]; + +const mappers: Provider[] = [UserMapper]; + +const repositories: Provider[] = [ + { + provide: USER_REPOSITORY, + useClass: UserRepository, + }, +]; + +const messagePublishers: Provider[] = [ + { + provide: USER_MESSAGE_PUBLISHER, + useExisting: MessageBrokerPublisher, + }, +]; + +const orms: Provider[] = [PrismaService]; @Module({ - imports: [ - DatabaseModule, - CqrsModule, - CacheModule.registerAsync({ - imports: [ConfigModule], - useFactory: async (configService: ConfigService) => ({ - store: await redisStore({ - host: configService.get('REDIS_HOST'), - port: configService.get('REDIS_PORT'), - password: configService.get('REDIS_PASSWORD'), - ttl: configService.get('CACHE_TTL'), - }), - }), - inject: [ConfigService], - }), - ], - controllers: [UserController], + imports, + controllers: [...grpcControllers], providers: [ - UserProfile, - UsersRepository, - FindAllUsersUseCase, - FindUserByUuidUseCase, - CreateUserUseCase, - UpdateUserUseCase, - DeleteUserUseCase, - { - provide: MESSAGE_BROKER_PUBLISHER, - useClass: MessageBrokerPublisher, - }, - { - provide: MESSAGE_PUBLISHER, - useClass: MessagePublisher, - }, + ...commandHandlers, + ...mappers, + ...repositories, + ...messagePublishers, + ...orms, ], - exports: [], + exports: [PrismaService, UserMapper, USER_REPOSITORY], }) export class UserModule {} From cc170779cbba1c7fb23b03791c3fbdad5a5c275b Mon Sep 17 00:00:00 2001 From: sbriat Date: Mon, 24 Jul 2023 09:56:20 +0200 Subject: [PATCH 3/9] fix update user service typo --- src/modules/user/tests/unit/core/update-user.service.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/user/tests/unit/core/update-user.service.spec.ts b/src/modules/user/tests/unit/core/update-user.service.spec.ts index 797f850..40554ee 100644 --- a/src/modules/user/tests/unit/core/update-user.service.spec.ts +++ b/src/modules/user/tests/unit/core/update-user.service.spec.ts @@ -85,7 +85,7 @@ describe('update-user.service', () => { }); describe('execution', () => { - it('should throw an exception if use is not found', async () => { + it('should throw an exception if user is not found', async () => { const updateUserCommand = new UpdateUserCommand( updateFirstNameUserRequest, ); From 979ea5e98feaba608d7b8e2d0a84ce7a8496f805 Mon Sep 17 00:00:00 2001 From: sbriat Date: Mon, 24 Jul 2023 10:13:27 +0200 Subject: [PATCH 4/9] findUserById --- .../find-user-by-id.query-handler.ts | 17 +++ .../find-user-by-id/find-user-by-id.query.ts | 10 ++ .../dtos/find-user-by-id.request.dto.ts | 7 ++ .../find-user-by-id.grpc.controller.ts | 46 ++++++++ .../find-user-by-id.query-handler.spec.ts | 58 ++++++++++ .../find-user-by-id.grpc.controller.spec.ts | 103 ++++++++++++++++++ 6 files changed, 241 insertions(+) create mode 100644 src/modules/user/core/application/queries/find-user-by-id/find-user-by-id.query-handler.ts create mode 100644 src/modules/user/core/application/queries/find-user-by-id/find-user-by-id.query.ts create mode 100644 src/modules/user/interface/grpc-controllers/dtos/find-user-by-id.request.dto.ts create mode 100644 src/modules/user/interface/grpc-controllers/find-user-by-id.grpc.controller.ts create mode 100644 src/modules/user/tests/unit/core/find-user-by-id.query-handler.spec.ts create mode 100644 src/modules/user/tests/unit/interface/find-user-by-id.grpc.controller.spec.ts diff --git a/src/modules/user/core/application/queries/find-user-by-id/find-user-by-id.query-handler.ts b/src/modules/user/core/application/queries/find-user-by-id/find-user-by-id.query-handler.ts new file mode 100644 index 0000000..3d1fb63 --- /dev/null +++ b/src/modules/user/core/application/queries/find-user-by-id/find-user-by-id.query-handler.ts @@ -0,0 +1,17 @@ +import { IQueryHandler, QueryHandler } from '@nestjs/cqrs'; +import { FindUserByIdQuery } from './find-user-by-id.query'; +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'; + +@QueryHandler(FindUserByIdQuery) +export class FindUserByIdQueryHandler implements IQueryHandler { + constructor( + @Inject(USER_REPOSITORY) + private readonly userRepository: UserRepositoryPort, + ) {} + async execute(query: FindUserByIdQuery): Promise { + return await this.userRepository.findOneById(query.id); + } +} diff --git a/src/modules/user/core/application/queries/find-user-by-id/find-user-by-id.query.ts b/src/modules/user/core/application/queries/find-user-by-id/find-user-by-id.query.ts new file mode 100644 index 0000000..53dd77b --- /dev/null +++ b/src/modules/user/core/application/queries/find-user-by-id/find-user-by-id.query.ts @@ -0,0 +1,10 @@ +import { QueryBase } from '@mobicoop/ddd-library'; + +export class FindUserByIdQuery extends QueryBase { + readonly id: string; + + constructor(id: string) { + super(); + this.id = id; + } +} diff --git a/src/modules/user/interface/grpc-controllers/dtos/find-user-by-id.request.dto.ts b/src/modules/user/interface/grpc-controllers/dtos/find-user-by-id.request.dto.ts new file mode 100644 index 0000000..edafb1e --- /dev/null +++ b/src/modules/user/interface/grpc-controllers/dtos/find-user-by-id.request.dto.ts @@ -0,0 +1,7 @@ +import { IsNotEmpty, IsString } from 'class-validator'; + +export class FindUserByIdRequestDto { + @IsString() + @IsNotEmpty() + id: string; +} diff --git a/src/modules/user/interface/grpc-controllers/find-user-by-id.grpc.controller.ts b/src/modules/user/interface/grpc-controllers/find-user-by-id.grpc.controller.ts new file mode 100644 index 0000000..22cf460 --- /dev/null +++ b/src/modules/user/interface/grpc-controllers/find-user-by-id.grpc.controller.ts @@ -0,0 +1,46 @@ +import { Controller, UsePipes } from '@nestjs/common'; +import { QueryBus } from '@nestjs/cqrs'; +import { GrpcMethod, RpcException } from '@nestjs/microservices'; +import { NotFoundException } from '@mobicoop/ddd-library'; +import { RpcExceptionCode } from '@mobicoop/ddd-library'; +import { RpcValidationPipe } from '@mobicoop/ddd-library'; +import { UserMapper } from '@modules/user/user.mapper'; +import { FindUserByIdRequestDto } from './dtos/find-user-by-id.request.dto'; +import { UserResponseDto } from '../dtos/user.response.dto'; +import { UserEntity } from '@modules/user/core/domain/user.entity'; +import { FindUserByIdQuery } from '@modules/user/core/application/queries/find-user-by-id/find-user-by-id.query'; + +@UsePipes( + new RpcValidationPipe({ + whitelist: false, + forbidUnknownValues: false, + }), +) +@Controller() +export class FindUserByIdGrpcController { + constructor( + protected readonly mapper: UserMapper, + private readonly queryBus: QueryBus, + ) {} + + @GrpcMethod('UserService', 'FindOneById') + async findOnebyId(data: FindUserByIdRequestDto): Promise { + try { + const user: UserEntity = await this.queryBus.execute( + new FindUserByIdQuery(data.id), + ); + return this.mapper.toResponse(user); + } catch (e) { + if (e instanceof NotFoundException) { + throw new RpcException({ + code: RpcExceptionCode.NOT_FOUND, + message: e.message, + }); + } + throw new RpcException({ + code: RpcExceptionCode.UNKNOWN, + message: e.message, + }); + } + } +} diff --git a/src/modules/user/tests/unit/core/find-user-by-id.query-handler.spec.ts b/src/modules/user/tests/unit/core/find-user-by-id.query-handler.spec.ts new file mode 100644 index 0000000..a2f3803 --- /dev/null +++ b/src/modules/user/tests/unit/core/find-user-by-id.query-handler.spec.ts @@ -0,0 +1,58 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { UserEntity } from '@modules/user/core/domain/user.entity'; +import { FindUserByIdQueryHandler } from '@modules/user/core/application/queries/find-user-by-id/find-user-by-id.query-handler'; +import { USER_REPOSITORY } from '@modules/user/user.di-tokens'; +import { FindUserByIdQuery } from '@modules/user/core/application/queries/find-user-by-id/find-user-by-id.query'; + +const now = new Date('2023-06-21 06:00:00'); +const user: 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 mockUserRepository = { + findOneById: jest.fn().mockImplementation(() => user), +}; + +describe('find-user-by-id.query-handler', () => { + let findUserByIdQueryHandler: FindUserByIdQueryHandler; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: USER_REPOSITORY, + useValue: mockUserRepository, + }, + FindUserByIdQueryHandler, + ], + }).compile(); + + findUserByIdQueryHandler = module.get( + FindUserByIdQueryHandler, + ); + }); + + it('should be defined', () => { + expect(findUserByIdQueryHandler).toBeDefined(); + }); + + describe('execution', () => { + it('should return a user', async () => { + const findUserbyIdQuery = new FindUserByIdQuery( + 'dd264806-13b4-4226-9b18-87adf0ad5dd1', + ); + const user: UserEntity = await findUserByIdQueryHandler.execute( + findUserbyIdQuery, + ); + expect(user.getProps().lastName).toBe('Doe'); + }); + }); +}); diff --git a/src/modules/user/tests/unit/interface/find-user-by-id.grpc.controller.spec.ts b/src/modules/user/tests/unit/interface/find-user-by-id.grpc.controller.spec.ts new file mode 100644 index 0000000..1f36cb7 --- /dev/null +++ b/src/modules/user/tests/unit/interface/find-user-by-id.grpc.controller.spec.ts @@ -0,0 +1,103 @@ +import { NotFoundException } from '@mobicoop/ddd-library'; +import { RpcExceptionCode } from '@mobicoop/ddd-library'; +import { FindUserByIdGrpcController } from '@modules/user/interface/grpc-controllers/find-user-by-id.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(() => '200d61a8-d878-4378-a609-c19ea71633d2') + .mockImplementationOnce(() => { + throw new NotFoundException(); + }) + .mockImplementationOnce(() => { + throw new Error(); + }), +}; + +const mockUserMapper = { + toResponse: jest.fn().mockImplementationOnce(() => ({ + firstName: 'John', + lastName: 'Doe', + email: 'john.doe@email.com', + phone: '+33611223344', + })), +}; + +describe('Find User By Id Grpc Controller', () => { + let findUserbyIdGrpcController: FindUserByIdGrpcController; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: QueryBus, + useValue: mockQueryBus, + }, + { + provide: UserMapper, + useValue: mockUserMapper, + }, + FindUserByIdGrpcController, + ], + }).compile(); + + findUserbyIdGrpcController = module.get( + FindUserByIdGrpcController, + ); + }); + + afterEach(async () => { + jest.clearAllMocks(); + }); + + it('should be defined', () => { + expect(findUserbyIdGrpcController).toBeDefined(); + }); + + it('should return a user', async () => { + jest.spyOn(mockQueryBus, 'execute'); + jest.spyOn(mockUserMapper, 'toResponse'); + const response = await findUserbyIdGrpcController.findOnebyId({ + id: '6dcf093c-c7db-4dae-8e9c-c715cebf83c7', + }); + expect(response.firstName).toBe('John'); + expect(mockQueryBus.execute).toHaveBeenCalledTimes(1); + expect(mockUserMapper.toResponse).toHaveBeenCalledTimes(1); + }); + + it('should throw a dedicated RpcException if user is not found', async () => { + jest.spyOn(mockQueryBus, 'execute'); + jest.spyOn(mockUserMapper, 'toResponse'); + expect.assertions(4); + try { + await findUserbyIdGrpcController.findOnebyId({ + id: 'ac85f5f4-41cd-4c5d-9aee-0a1acb176fb8', + }); + } catch (e: any) { + expect(e).toBeInstanceOf(RpcException); + expect(e.error.code).toBe(RpcExceptionCode.NOT_FOUND); + } + expect(mockQueryBus.execute).toHaveBeenCalledTimes(1); + expect(mockUserMapper.toResponse).toHaveBeenCalledTimes(0); + }); + + it('should throw a generic RpcException', async () => { + jest.spyOn(mockQueryBus, 'execute'); + jest.spyOn(mockUserMapper, 'toResponse'); + expect.assertions(4); + try { + await findUserbyIdGrpcController.findOnebyId({ + id: '53c8e7ec-ef68-42bc-ba4c-5ef3effa60a6', + }); + } catch (e: any) { + expect(e).toBeInstanceOf(RpcException); + expect(e.error.code).toBe(RpcExceptionCode.UNKNOWN); + } + expect(mockQueryBus.execute).toHaveBeenCalledTimes(1); + expect(mockUserMapper.toResponse).toHaveBeenCalledTimes(0); + }); +}); From 3ac7460c833b2788f2ba473cd0fedd0a2f66918d Mon Sep 17 00:00:00 2001 From: sbriat Date: Mon, 24 Jul 2023 11:25:46 +0200 Subject: [PATCH 5/9] domain event handlers --- .../delete-user/delete-user.command.ts | 7 ++ .../delete-user/delete-user.service.ts | 21 ++++ ...en-user-is-created.domain-event-handler.ts | 18 ++++ ...en-user-is-deleted.domain-event-handler.ts | 18 ++++ ...en-user-is-updated.domain-event-handler.ts | 18 ++++ .../events/user-deleted.domain-event.ts | 7 ++ src/modules/user/core/domain/user.entity.ts | 9 ++ .../delete-user.grpc.controller.ts | 44 +++++++++ .../dtos/delete-user.request.dto.ts | 7 ++ .../unit/core/delete-user.service.spec.ts | 50 ++++++++++ ...er-is-created.domain-event-handler.spec.ts | 54 ++++++++++ ...er-is-deleted.domain-event-handler.spec.ts | 54 ++++++++++ ...er-is-updated.domain-event-handler.spec.ts | 54 ++++++++++ .../user/tests/unit/core/user.entity.spec.ts | 39 +++++++- .../delete-user.grpc.controller.spec.ts | 99 +++++++++++++++++++ 15 files changed, 498 insertions(+), 1 deletion(-) create mode 100644 src/modules/user/core/application/commands/delete-user/delete-user.command.ts create mode 100644 src/modules/user/core/application/commands/delete-user/delete-user.service.ts create mode 100644 src/modules/user/core/application/event-handlers/publish-message-when-user-is-created.domain-event-handler.ts create mode 100644 src/modules/user/core/application/event-handlers/publish-message-when-user-is-deleted.domain-event-handler.ts create mode 100644 src/modules/user/core/application/event-handlers/publish-message-when-user-is-updated.domain-event-handler.ts create mode 100644 src/modules/user/core/domain/events/user-deleted.domain-event.ts create mode 100644 src/modules/user/interface/grpc-controllers/delete-user.grpc.controller.ts create mode 100644 src/modules/user/interface/grpc-controllers/dtos/delete-user.request.dto.ts create mode 100644 src/modules/user/tests/unit/core/delete-user.service.spec.ts create mode 100644 src/modules/user/tests/unit/core/publish-message-when-user-is-created.domain-event-handler.spec.ts create mode 100644 src/modules/user/tests/unit/core/publish-message-when-user-is-deleted.domain-event-handler.spec.ts create mode 100644 src/modules/user/tests/unit/core/publish-message-when-user-is-updated.domain-event-handler.spec.ts create mode 100644 src/modules/user/tests/unit/interface/delete-user.grpc.controller.spec.ts diff --git a/src/modules/user/core/application/commands/delete-user/delete-user.command.ts b/src/modules/user/core/application/commands/delete-user/delete-user.command.ts new file mode 100644 index 0000000..2f2f037 --- /dev/null +++ b/src/modules/user/core/application/commands/delete-user/delete-user.command.ts @@ -0,0 +1,7 @@ +import { Command, CommandProps } from '@mobicoop/ddd-library'; + +export class DeleteUserCommand extends Command { + constructor(props: CommandProps) { + super(props); + } +} diff --git a/src/modules/user/core/application/commands/delete-user/delete-user.service.ts b/src/modules/user/core/application/commands/delete-user/delete-user.service.ts new file mode 100644 index 0000000..294b37c --- /dev/null +++ b/src/modules/user/core/application/commands/delete-user/delete-user.service.ts @@ -0,0 +1,21 @@ +import { Inject } from '@nestjs/common'; +import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'; +import { DeleteUserCommand } from './delete-user.command'; +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'; + +@CommandHandler(DeleteUserCommand) +export class DeleteUserService implements ICommandHandler { + constructor( + @Inject(USER_REPOSITORY) + private readonly userRepository: UserRepositoryPort, + ) {} + + async execute(command: DeleteUserCommand): Promise { + const user: UserEntity = await this.userRepository.findOneById(command.id); + user.delete(); + const isDeleted: boolean = await this.userRepository.delete(user); + return isDeleted; + } +} diff --git a/src/modules/user/core/application/event-handlers/publish-message-when-user-is-created.domain-event-handler.ts b/src/modules/user/core/application/event-handlers/publish-message-when-user-is-created.domain-event-handler.ts new file mode 100644 index 0000000..3fcab00 --- /dev/null +++ b/src/modules/user/core/application/event-handlers/publish-message-when-user-is-created.domain-event-handler.ts @@ -0,0 +1,18 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { OnEvent } from '@nestjs/event-emitter'; +import { MessagePublisherPort } from '@mobicoop/ddd-library'; +import { USER_MESSAGE_PUBLISHER } from '@modules/user/user.di-tokens'; +import { UserCreatedDomainEvent } from '../../domain/events/user-created.domain-events'; + +@Injectable() +export class PublishMessageWhenUserIsCreatedDomainEventHandler { + constructor( + @Inject(USER_MESSAGE_PUBLISHER) + private readonly messagePublisher: MessagePublisherPort, + ) {} + + @OnEvent(UserCreatedDomainEvent.name, { async: true, promisify: true }) + async handle(event: UserCreatedDomainEvent): Promise { + this.messagePublisher.publish('user.created', JSON.stringify(event)); + } +} diff --git a/src/modules/user/core/application/event-handlers/publish-message-when-user-is-deleted.domain-event-handler.ts b/src/modules/user/core/application/event-handlers/publish-message-when-user-is-deleted.domain-event-handler.ts new file mode 100644 index 0000000..d3c2893 --- /dev/null +++ b/src/modules/user/core/application/event-handlers/publish-message-when-user-is-deleted.domain-event-handler.ts @@ -0,0 +1,18 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { OnEvent } from '@nestjs/event-emitter'; +import { MessagePublisherPort } from '@mobicoop/ddd-library'; +import { USER_MESSAGE_PUBLISHER } from '@modules/user/user.di-tokens'; +import { UserDeletedDomainEvent } from '../../domain/events/user-deleted.domain-event'; + +@Injectable() +export class PublishMessageWhenUserIsDeletedDomainEventHandler { + constructor( + @Inject(USER_MESSAGE_PUBLISHER) + private readonly messagePublisher: MessagePublisherPort, + ) {} + + @OnEvent(UserDeletedDomainEvent.name, { async: true, promisify: true }) + async handle(event: UserDeletedDomainEvent): Promise { + this.messagePublisher.publish('user.deleted', JSON.stringify(event)); + } +} diff --git a/src/modules/user/core/application/event-handlers/publish-message-when-user-is-updated.domain-event-handler.ts b/src/modules/user/core/application/event-handlers/publish-message-when-user-is-updated.domain-event-handler.ts new file mode 100644 index 0000000..90b51b1 --- /dev/null +++ b/src/modules/user/core/application/event-handlers/publish-message-when-user-is-updated.domain-event-handler.ts @@ -0,0 +1,18 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { OnEvent } from '@nestjs/event-emitter'; +import { MessagePublisherPort } from '@mobicoop/ddd-library'; +import { USER_MESSAGE_PUBLISHER } from '@modules/user/user.di-tokens'; +import { UserUpdatedDomainEvent } from '../../domain/events/user-updated.domain-events'; + +@Injectable() +export class PublishMessageWhenUserIsUpdatedDomainEventHandler { + constructor( + @Inject(USER_MESSAGE_PUBLISHER) + private readonly messagePublisher: MessagePublisherPort, + ) {} + + @OnEvent(UserUpdatedDomainEvent.name, { async: true, promisify: true }) + async handle(event: UserUpdatedDomainEvent): Promise { + this.messagePublisher.publish('user.updated', JSON.stringify(event)); + } +} diff --git a/src/modules/user/core/domain/events/user-deleted.domain-event.ts b/src/modules/user/core/domain/events/user-deleted.domain-event.ts new file mode 100644 index 0000000..2f28885 --- /dev/null +++ b/src/modules/user/core/domain/events/user-deleted.domain-event.ts @@ -0,0 +1,7 @@ +import { DomainEvent, DomainEventProps } from '@mobicoop/ddd-library'; + +export class UserDeletedDomainEvent extends DomainEvent { + constructor(props: DomainEventProps) { + super(props); + } +} diff --git a/src/modules/user/core/domain/user.entity.ts b/src/modules/user/core/domain/user.entity.ts index 0bb810f..7c6448a 100644 --- a/src/modules/user/core/domain/user.entity.ts +++ b/src/modules/user/core/domain/user.entity.ts @@ -3,6 +3,7 @@ import { v4 } from 'uuid'; import { CreateUserProps, UpdateUserProps, UserProps } from './user.types'; import { UserCreatedDomainEvent } from './events/user-created.domain-events'; import { UserUpdatedDomainEvent } from './events/user-updated.domain-events'; +import { UserDeletedDomainEvent } from './events/user-deleted.domain-event'; export class UserEntity extends AggregateRoot { protected readonly _id: AggregateID; @@ -40,6 +41,14 @@ export class UserEntity extends AggregateRoot { ); } + delete(): void { + this.addEvent( + new UserDeletedDomainEvent({ + aggregateId: this.id, + }), + ); + } + validate(): void { // entity business rules validation to protect it's invariant before saving entity to a database } diff --git a/src/modules/user/interface/grpc-controllers/delete-user.grpc.controller.ts b/src/modules/user/interface/grpc-controllers/delete-user.grpc.controller.ts new file mode 100644 index 0000000..9e1cd5c --- /dev/null +++ b/src/modules/user/interface/grpc-controllers/delete-user.grpc.controller.ts @@ -0,0 +1,44 @@ +import { + DatabaseErrorException, + NotFoundException, + RpcExceptionCode, + RpcValidationPipe, +} from '@mobicoop/ddd-library'; +import { Controller, UsePipes } from '@nestjs/common'; +import { CommandBus } from '@nestjs/cqrs'; +import { GrpcMethod, RpcException } from '@nestjs/microservices'; +import { DeleteUserRequestDto } from './dtos/delete-user.request.dto'; +import { DeleteUserCommand } from '@modules/user/core/application/commands/delete-user/delete-user.command'; + +@UsePipes( + new RpcValidationPipe({ + whitelist: true, + forbidUnknownValues: false, + }), +) +@Controller() +export class DeleteUserGrpcController { + constructor(private readonly commandBus: CommandBus) {} + + @GrpcMethod('UserService', 'Delete') + async delete(data: DeleteUserRequestDto): Promise { + try { + await this.commandBus.execute(new DeleteUserCommand(data)); + } catch (error: any) { + if (error instanceof NotFoundException) + throw new RpcException({ + code: RpcExceptionCode.NOT_FOUND, + message: error.message, + }); + if (error instanceof DatabaseErrorException) + throw new RpcException({ + code: RpcExceptionCode.INTERNAL, + message: error.message, + }); + throw new RpcException({ + code: RpcExceptionCode.UNKNOWN, + message: error.message, + }); + } + } +} diff --git a/src/modules/user/interface/grpc-controllers/dtos/delete-user.request.dto.ts b/src/modules/user/interface/grpc-controllers/dtos/delete-user.request.dto.ts new file mode 100644 index 0000000..bf364f3 --- /dev/null +++ b/src/modules/user/interface/grpc-controllers/dtos/delete-user.request.dto.ts @@ -0,0 +1,7 @@ +import { IsNotEmpty, IsString } from 'class-validator'; + +export class DeleteUserRequestDto { + @IsString() + @IsNotEmpty() + id: string; +} diff --git a/src/modules/user/tests/unit/core/delete-user.service.spec.ts b/src/modules/user/tests/unit/core/delete-user.service.spec.ts new file mode 100644 index 0000000..fb7fa7e --- /dev/null +++ b/src/modules/user/tests/unit/core/delete-user.service.spec.ts @@ -0,0 +1,50 @@ +import { DeleteUserCommand } from '@modules/user/core/application/commands/delete-user/delete-user.command'; +import { DeleteUserService } from '@modules/user/core/application/commands/delete-user/delete-user.service'; +import { DeleteUserRequestDto } from '@modules/user/interface/grpc-controllers/dtos/delete-user.request.dto'; +import { USER_REPOSITORY } from '@modules/user/user.di-tokens'; +import { Test, TestingModule } from '@nestjs/testing'; + +const deleteUserRequest: DeleteUserRequestDto = { + id: '165192d4-398a-4469-a16b-98c02cc6f531', +}; + +const mockUserEntity = { + delete: jest.fn(), +}; + +const mockUserRepository = { + findOneById: jest.fn().mockImplementation(() => mockUserEntity), + delete: jest.fn().mockImplementationOnce(() => true), +}; + +describe('Delete User Service', () => { + let deleteUserService: DeleteUserService; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: USER_REPOSITORY, + useValue: mockUserRepository, + }, + DeleteUserService, + ], + }).compile(); + + deleteUserService = module.get(DeleteUserService); + }); + + it('should be defined', () => { + expect(deleteUserService).toBeDefined(); + }); + + describe('execution', () => { + const deleteUserCommand = new DeleteUserCommand(deleteUserRequest); + it('should delete a user', async () => { + const result: boolean = await deleteUserService.execute( + deleteUserCommand, + ); + expect(result).toBeTruthy(); + }); + }); +}); diff --git a/src/modules/user/tests/unit/core/publish-message-when-user-is-created.domain-event-handler.spec.ts b/src/modules/user/tests/unit/core/publish-message-when-user-is-created.domain-event-handler.spec.ts new file mode 100644 index 0000000..0b03b0f --- /dev/null +++ b/src/modules/user/tests/unit/core/publish-message-when-user-is-created.domain-event-handler.spec.ts @@ -0,0 +1,54 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { PublishMessageWhenUserIsCreatedDomainEventHandler } from '@modules/user/core/application/event-handlers/publish-message-when-user-is-created.domain-event-handler'; +import { USER_MESSAGE_PUBLISHER } from '@modules/user/user.di-tokens'; +import { UserCreatedDomainEvent } from '@modules/user/core/domain/events/user-created.domain-events'; + +const mockMessagePublisher = { + publish: jest.fn().mockImplementation(), +}; + +describe('Publish message when user is created domain event handler', () => { + let publishMessageWhenUserIsCreatedDomainEventHandler: PublishMessageWhenUserIsCreatedDomainEventHandler; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: USER_MESSAGE_PUBLISHER, + useValue: mockMessagePublisher, + }, + PublishMessageWhenUserIsCreatedDomainEventHandler, + ], + }).compile(); + + publishMessageWhenUserIsCreatedDomainEventHandler = + module.get( + PublishMessageWhenUserIsCreatedDomainEventHandler, + ); + }); + + it('should publish a message', () => { + jest.spyOn(mockMessagePublisher, 'publish'); + const userCreatedDomainEvent: UserCreatedDomainEvent = { + id: 'some-domain-event-id', + aggregateId: 'some-aggregate-id', + firstName: 'John', + lastName: 'Doe', + email: 'john.doe@email.com', + phone: '+33611223344', + metadata: { + timestamp: new Date('2023-06-28T05:00:00Z').getTime(), + correlationId: 'some-correlation-id', + }, + }; + publishMessageWhenUserIsCreatedDomainEventHandler.handle( + userCreatedDomainEvent, + ); + expect(publishMessageWhenUserIsCreatedDomainEventHandler).toBeDefined(); + expect(mockMessagePublisher.publish).toHaveBeenCalledTimes(1); + expect(mockMessagePublisher.publish).toHaveBeenCalledWith( + 'user.created', + '{"id":"some-domain-event-id","aggregateId":"some-aggregate-id","firstName":"John","lastName":"Doe","email":"john.doe@email.com","phone":"+33611223344","metadata":{"timestamp":1687928400000,"correlationId":"some-correlation-id"}}', + ); + }); +}); diff --git a/src/modules/user/tests/unit/core/publish-message-when-user-is-deleted.domain-event-handler.spec.ts b/src/modules/user/tests/unit/core/publish-message-when-user-is-deleted.domain-event-handler.spec.ts new file mode 100644 index 0000000..c4add5d --- /dev/null +++ b/src/modules/user/tests/unit/core/publish-message-when-user-is-deleted.domain-event-handler.spec.ts @@ -0,0 +1,54 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { USER_MESSAGE_PUBLISHER } from '@modules/user/user.di-tokens'; +import { UserCreatedDomainEvent } from '@modules/user/core/domain/events/user-created.domain-events'; +import { PublishMessageWhenUserIsDeletedDomainEventHandler } from '@modules/user/core/application/event-handlers/publish-message-when-user-is-deleted.domain-event-handler'; + +const mockMessagePublisher = { + publish: jest.fn().mockImplementation(), +}; + +describe('Publish message when user is deleted domain event handler', () => { + let publishMessageWhenUserIsDeletedDomainEventHandler: PublishMessageWhenUserIsDeletedDomainEventHandler; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: USER_MESSAGE_PUBLISHER, + useValue: mockMessagePublisher, + }, + PublishMessageWhenUserIsDeletedDomainEventHandler, + ], + }).compile(); + + publishMessageWhenUserIsDeletedDomainEventHandler = + module.get( + PublishMessageWhenUserIsDeletedDomainEventHandler, + ); + }); + + it('should publish a message', () => { + jest.spyOn(mockMessagePublisher, 'publish'); + const userDeletedDomainEvent: UserCreatedDomainEvent = { + id: 'some-domain-event-id', + aggregateId: 'some-aggregate-id', + firstName: 'John', + lastName: 'Doe', + email: 'john.doe@email.com', + phone: '+33611223344', + metadata: { + timestamp: new Date('2023-06-28T05:00:00Z').getTime(), + correlationId: 'some-correlation-id', + }, + }; + publishMessageWhenUserIsDeletedDomainEventHandler.handle( + userDeletedDomainEvent, + ); + expect(publishMessageWhenUserIsDeletedDomainEventHandler).toBeDefined(); + expect(mockMessagePublisher.publish).toHaveBeenCalledTimes(1); + expect(mockMessagePublisher.publish).toHaveBeenCalledWith( + 'user.deleted', + '{"id":"some-domain-event-id","aggregateId":"some-aggregate-id","firstName":"John","lastName":"Doe","email":"john.doe@email.com","phone":"+33611223344","metadata":{"timestamp":1687928400000,"correlationId":"some-correlation-id"}}', + ); + }); +}); diff --git a/src/modules/user/tests/unit/core/publish-message-when-user-is-updated.domain-event-handler.spec.ts b/src/modules/user/tests/unit/core/publish-message-when-user-is-updated.domain-event-handler.spec.ts new file mode 100644 index 0000000..af36963 --- /dev/null +++ b/src/modules/user/tests/unit/core/publish-message-when-user-is-updated.domain-event-handler.spec.ts @@ -0,0 +1,54 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { USER_MESSAGE_PUBLISHER } from '@modules/user/user.di-tokens'; +import { PublishMessageWhenUserIsUpdatedDomainEventHandler } from '@modules/user/core/application/event-handlers/publish-message-when-user-is-updated.domain-event-handler'; +import { UserUpdatedDomainEvent } from '@modules/user/core/domain/events/user-updated.domain-events'; + +const mockMessagePublisher = { + publish: jest.fn().mockImplementation(), +}; + +describe('Publish message when user is updated domain event handler', () => { + let publishMessageWhenUserIsUpdatedDomainEventHandler: PublishMessageWhenUserIsUpdatedDomainEventHandler; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: USER_MESSAGE_PUBLISHER, + useValue: mockMessagePublisher, + }, + PublishMessageWhenUserIsUpdatedDomainEventHandler, + ], + }).compile(); + + publishMessageWhenUserIsUpdatedDomainEventHandler = + module.get( + PublishMessageWhenUserIsUpdatedDomainEventHandler, + ); + }); + + it('should publish a message', () => { + jest.spyOn(mockMessagePublisher, 'publish'); + const userUpdatedDomainEvent: UserUpdatedDomainEvent = { + id: 'some-domain-event-id', + aggregateId: 'some-aggregate-id', + firstName: 'Jane', + lastName: 'Doe', + email: 'jane.doe@email.com', + phone: '+33611223344', + metadata: { + timestamp: new Date('2023-06-28T05:00:00Z').getTime(), + correlationId: 'some-correlation-id', + }, + }; + publishMessageWhenUserIsUpdatedDomainEventHandler.handle( + userUpdatedDomainEvent, + ); + expect(publishMessageWhenUserIsUpdatedDomainEventHandler).toBeDefined(); + expect(mockMessagePublisher.publish).toHaveBeenCalledTimes(1); + expect(mockMessagePublisher.publish).toHaveBeenCalledWith( + 'user.updated', + '{"id":"some-domain-event-id","aggregateId":"some-aggregate-id","firstName":"Jane","lastName":"Doe","email":"jane.doe@email.com","phone":"+33611223344","metadata":{"timestamp":1687928400000,"correlationId":"some-correlation-id"}}', + ); + }); +}); diff --git a/src/modules/user/tests/unit/core/user.entity.spec.ts b/src/modules/user/tests/unit/core/user.entity.spec.ts index 32aa437..6a3d471 100644 --- a/src/modules/user/tests/unit/core/user.entity.spec.ts +++ b/src/modules/user/tests/unit/core/user.entity.spec.ts @@ -1,5 +1,11 @@ +import { UserCreatedDomainEvent } from '@modules/user/core/domain/events/user-created.domain-events'; +import { UserDeletedDomainEvent } from '@modules/user/core/domain/events/user-deleted.domain-event'; +import { UserUpdatedDomainEvent } from '@modules/user/core/domain/events/user-updated.domain-events'; import { UserEntity } from '@modules/user/core/domain/user.entity'; -import { CreateUserProps } from '@modules/user/core/domain/user.types'; +import { + CreateUserProps, + UpdateUserProps, +} from '@modules/user/core/domain/user.types'; const createUserProps: CreateUserProps = { firstName: 'John', @@ -8,10 +14,41 @@ const createUserProps: CreateUserProps = { phone: '+33611223344', }; +const updateUserProps: UpdateUserProps = { + firstName: 'Jane', + lastName: 'Dane', + email: 'jane.dane@email.com', +}; + describe('User entity create', () => { it('should create a new user entity', async () => { const userEntity: UserEntity = UserEntity.create(createUserProps); expect(userEntity.id.length).toBe(36); expect(userEntity.getProps().email).toBe('john.doe@email.com'); + expect(userEntity.domainEvents.length).toBe(1); + expect(userEntity.domainEvents[0]).toBeInstanceOf(UserCreatedDomainEvent); + }); +}); + +describe('User entity update', () => { + it('should update a user entity', async () => { + const userEntity: UserEntity = UserEntity.create(createUserProps); + userEntity.update(updateUserProps); + expect(userEntity.getProps().firstName).toBe('Jane'); + expect(userEntity.getProps().lastName).toBe('Dane'); + expect(userEntity.getProps().email).toBe('jane.dane@email.com'); + // 2 events because UserEntity.create sends a UserCreatedDomainEvent + expect(userEntity.domainEvents.length).toBe(2); + expect(userEntity.domainEvents[1]).toBeInstanceOf(UserUpdatedDomainEvent); + }); +}); + +describe('User entity delete', () => { + it('should delete a user entity', async () => { + const userEntity: UserEntity = UserEntity.create(createUserProps); + userEntity.delete(); + // 2 events because UserEntity.create sends a UserCreatedDomainEvent + expect(userEntity.domainEvents.length).toBe(2); + expect(userEntity.domainEvents[1]).toBeInstanceOf(UserDeletedDomainEvent); }); }); diff --git a/src/modules/user/tests/unit/interface/delete-user.grpc.controller.spec.ts b/src/modules/user/tests/unit/interface/delete-user.grpc.controller.spec.ts new file mode 100644 index 0000000..ebdff5c --- /dev/null +++ b/src/modules/user/tests/unit/interface/delete-user.grpc.controller.spec.ts @@ -0,0 +1,99 @@ +import { + DatabaseErrorException, + NotFoundException, +} from '@mobicoop/ddd-library'; +import { RpcExceptionCode } from '@mobicoop/ddd-library'; +import { DeleteUserGrpcController } from '@modules/user/interface/grpc-controllers/delete-user.grpc.controller'; +import { DeleteUserRequestDto } from '@modules/user/interface/grpc-controllers/dtos/delete-user.request.dto'; +import { CommandBus } from '@nestjs/cqrs'; +import { RpcException } from '@nestjs/microservices'; +import { Test, TestingModule } from '@nestjs/testing'; + +const deleteUserRequest: DeleteUserRequestDto = { + id: '78153e03-4861-4f58-a705-88526efee53b', +}; + +const mockCommandBus = { + execute: jest + .fn() + .mockImplementationOnce(() => ({})) + .mockImplementationOnce(() => { + throw new NotFoundException(); + }) + .mockImplementationOnce(() => { + throw new DatabaseErrorException(); + }) + .mockImplementationOnce(() => { + throw new Error(); + }), +}; + +describe('Delete User Grpc Controller', () => { + let deleteUserGrpcController: DeleteUserGrpcController; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: CommandBus, + useValue: mockCommandBus, + }, + DeleteUserGrpcController, + ], + }).compile(); + + deleteUserGrpcController = module.get( + DeleteUserGrpcController, + ); + }); + + afterEach(async () => { + jest.clearAllMocks(); + }); + + it('should be defined', () => { + expect(deleteUserGrpcController).toBeDefined(); + }); + + it('should delete a user', async () => { + jest.spyOn(mockCommandBus, 'execute'); + await deleteUserGrpcController.delete(deleteUserRequest); + expect(mockCommandBus.execute).toHaveBeenCalledTimes(1); + }); + + it('should throw a dedicated RpcException if user does not exist', async () => { + jest.spyOn(mockCommandBus, 'execute'); + expect.assertions(3); + try { + await deleteUserGrpcController.delete(deleteUserRequest); + } catch (e: any) { + expect(e).toBeInstanceOf(RpcException); + expect(e.error.code).toBe(RpcExceptionCode.NOT_FOUND); + } + expect(mockCommandBus.execute).toHaveBeenCalledTimes(1); + }); + + it('should throw a dedicated RpcException if a database error occurs', async () => { + jest.spyOn(mockCommandBus, 'execute'); + expect.assertions(3); + try { + await deleteUserGrpcController.delete(deleteUserRequest); + } catch (e: any) { + expect(e).toBeInstanceOf(RpcException); + expect(e.error.code).toBe(RpcExceptionCode.INTERNAL); + } + expect(mockCommandBus.execute).toHaveBeenCalledTimes(1); + }); + + it('should throw a generic RpcException', async () => { + jest.spyOn(mockCommandBus, 'execute'); + expect.assertions(3); + try { + await deleteUserGrpcController.delete(deleteUserRequest); + } catch (e: any) { + expect(e).toBeInstanceOf(RpcException); + expect(e.error.code).toBe(RpcExceptionCode.UNKNOWN); + } + expect(mockCommandBus.execute).toHaveBeenCalledTimes(1); + }); +}); From e8c40a63866e184f8991de3d5f319691823fa817 Mon Sep 17 00:00:00 2001 From: sbriat Date: Mon, 24 Jul 2023 15:06:15 +0200 Subject: [PATCH 6/9] integration events --- .old/adapters/primaries/user.controller.ts | 121 - .old/adapters/primaries/user.presenter.ts | 18 - .old/adapters/primaries/user.proto | 35 - .../adapters/secondaries/message-publisher.ts | 16 - .old/adapters/secondaries/users.repository.ts | 8 - .old/commands/create-user.command.ts | 9 - .old/commands/delete-user.command.ts | 7 - .old/commands/update-user.command.ts | 9 - .old/domain/dtos/create-user.request.ts | 29 - .old/domain/dtos/find-all-users.request.ts | 11 - .old/domain/dtos/find-user-by-uuid.request.ts | 7 - .old/domain/dtos/update-user.request.ts | 35 - .old/domain/entities/user.ts | 18 - .old/domain/usecases/create-user.usecase.ts | 51 - .old/domain/usecases/delete-user.usecase.ts | 40 - .../domain/usecases/find-all-users.usecase.ts | 15 - .../usecases/find-user-by-uuid.usecase.ts | 33 - .old/domain/usecases/update-user.usecase.ts | 53 - .old/mappers/user.profile.ts | 29 - .old/queries/find-all-users.query.ts | 11 - .old/queries/find-user-by-uuid.query.ts | 9 - .../tests/unit/find-all-users.usecase.spec.ts | 74 - .../unit/find-user-by-uuid.usecase.spec.ts | 82 - package-lock.json | 2638 ++++++----------- package.json | 4 +- ...en-user-is-created.domain-event-handler.ts | 17 +- ...en-user-is-deleted.domain-event-handler.ts | 11 +- ...en-user-is-updated.domain-event-handler.ts | 17 +- .../events/user-created.integration-event.ts | 16 + .../events/user-deleted.integration-event.ts | 7 + .../events/user-updated.integration-event.ts | 16 + ...events.ts => user-created.domain-event.ts} | 0 ...events.ts => user-updated.domain-event.ts} | 0 src/modules/user/core/domain/user.entity.ts | 4 +- .../user/infrastructure/user.repository.ts | 13 +- .../update-user.grpc.controller.ts | 3 +- ...er-is-created.domain-event-handler.spec.ts | 4 +- ...er-is-deleted.domain-event-handler.spec.ts | 4 +- ...er-is-updated.domain-event-handler.spec.ts | 4 +- .../user/tests/unit/core/user.entity.spec.ts | 4 +- .../user/tests/unit/user.mapper.spec.ts | 11 +- src/modules/user/user.constants.ts | 3 + src/modules/user/user.mapper.ts | 23 +- src/modules/user/user.module.ts | 30 +- 44 files changed, 1053 insertions(+), 2496 deletions(-) delete mode 100644 .old/adapters/primaries/user.controller.ts delete mode 100644 .old/adapters/primaries/user.presenter.ts delete mode 100644 .old/adapters/primaries/user.proto delete mode 100644 .old/adapters/secondaries/message-publisher.ts delete mode 100644 .old/adapters/secondaries/users.repository.ts delete mode 100644 .old/commands/create-user.command.ts delete mode 100644 .old/commands/delete-user.command.ts delete mode 100644 .old/commands/update-user.command.ts delete mode 100644 .old/domain/dtos/create-user.request.ts delete mode 100644 .old/domain/dtos/find-all-users.request.ts delete mode 100644 .old/domain/dtos/find-user-by-uuid.request.ts delete mode 100644 .old/domain/dtos/update-user.request.ts delete mode 100644 .old/domain/entities/user.ts delete mode 100644 .old/domain/usecases/create-user.usecase.ts delete mode 100644 .old/domain/usecases/delete-user.usecase.ts delete mode 100644 .old/domain/usecases/find-all-users.usecase.ts delete mode 100644 .old/domain/usecases/find-user-by-uuid.usecase.ts delete mode 100644 .old/domain/usecases/update-user.usecase.ts delete mode 100644 .old/mappers/user.profile.ts delete mode 100644 .old/queries/find-all-users.query.ts delete mode 100644 .old/queries/find-user-by-uuid.query.ts delete mode 100644 .old/tests/unit/find-all-users.usecase.spec.ts delete mode 100644 .old/tests/unit/find-user-by-uuid.usecase.spec.ts create mode 100644 src/modules/user/core/application/events/user-created.integration-event.ts create mode 100644 src/modules/user/core/application/events/user-deleted.integration-event.ts create mode 100644 src/modules/user/core/application/events/user-updated.integration-event.ts rename src/modules/user/core/domain/events/{user-created.domain-events.ts => user-created.domain-event.ts} (100%) rename src/modules/user/core/domain/events/{user-updated.domain-events.ts => user-updated.domain-event.ts} (100%) create mode 100644 src/modules/user/user.constants.ts diff --git a/.old/adapters/primaries/user.controller.ts b/.old/adapters/primaries/user.controller.ts deleted file mode 100644 index fd2d0aa..0000000 --- a/.old/adapters/primaries/user.controller.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { Mapper } from '@automapper/core'; -import { InjectMapper } from '@automapper/nestjs'; -import { Controller, UseInterceptors, UsePipes } from '@nestjs/common'; -import { CommandBus, QueryBus } from '@nestjs/cqrs'; -import { GrpcMethod, RpcException } from '@nestjs/microservices'; -import { DatabaseException } from '../../../database/exceptions/database.exception'; -import { CreateUserCommand } from '../../commands/create-user.command'; -import { DeleteUserCommand } from '../../commands/delete-user.command'; -import { UpdateUserCommand } from '../../commands/update-user.command'; -import { CreateUserRequest } from '../../domain/dtos/create-user.request'; -import { FindAllUsersRequest } from '../../domain/dtos/find-all-users.request'; -import { FindUserByUuidRequest } from '../../domain/dtos/find-user-by-uuid.request'; -import { UpdateUserRequest } from '../../domain/dtos/update-user.request'; -import { User } from '../../domain/entities/user'; -import { FindAllUsersQuery } from '../../queries/find-all-users.query'; -import { FindUserByUuidQuery } from '../../queries/find-user-by-uuid.query'; -import { UserPresenter } from './user.presenter'; -import { ICollection } from '../../../database/interfaces/collection.interface'; -import { RpcValidationPipe } from '../../../../utils/pipes/rpc.validation-pipe'; -import { CacheInterceptor, CacheKey } from '@nestjs/cache-manager'; - -@UsePipes( - new RpcValidationPipe({ - whitelist: true, - forbidUnknownValues: false, - }), -) -@Controller() -export class UserController { - constructor( - private readonly commandBus: CommandBus, - private readonly queryBus: QueryBus, - @InjectMapper() private readonly mapper: Mapper, - ) {} - - @GrpcMethod('UsersService', 'FindAll') - @UseInterceptors(CacheInterceptor) - @CacheKey('UsersServiceFindAll') - async findAll(data: FindAllUsersRequest): Promise> { - const userCollection = await this.queryBus.execute( - new FindAllUsersQuery(data), - ); - return Promise.resolve({ - data: userCollection.data.map((user: User) => - this.mapper.map(user, User, UserPresenter), - ), - total: userCollection.total, - }); - } - - @GrpcMethod('UsersService', 'FindOneByUuid') - @UseInterceptors(CacheInterceptor) - @CacheKey('UsersServiceFindOneByUuid') - async findOneByUuid(data: FindUserByUuidRequest): Promise { - try { - const user = await this.queryBus.execute(new FindUserByUuidQuery(data)); - return this.mapper.map(user, User, UserPresenter); - } catch (error) { - throw new RpcException({ - code: 5, - message: 'User not found', - }); - } - } - - @GrpcMethod('UsersService', 'Create') - async createUser(data: CreateUserRequest): Promise { - try { - const user = await this.commandBus.execute(new CreateUserCommand(data)); - return this.mapper.map(user, User, UserPresenter); - } catch (e) { - if (e instanceof DatabaseException) { - if (e.message.includes('Already exists')) { - throw new RpcException({ - code: 6, - message: 'User already exists', - }); - } - } - throw new RpcException({}); - } - } - - @GrpcMethod('UsersService', 'Update') - async updateUser(data: UpdateUserRequest): Promise { - try { - const user = await this.commandBus.execute(new UpdateUserCommand(data)); - - return this.mapper.map(user, User, UserPresenter); - } catch (e) { - if (e instanceof DatabaseException) { - if (e.message.includes('not found')) { - throw new RpcException({ - code: 5, - message: 'User not found', - }); - } - } - throw new RpcException({}); - } - } - - @GrpcMethod('UsersService', 'Delete') - async deleteUser(data: FindUserByUuidRequest): Promise { - try { - await this.commandBus.execute(new DeleteUserCommand(data.uuid)); - - return Promise.resolve(); - } catch (e) { - if (e instanceof DatabaseException) { - if (e.message.includes('not found')) { - throw new RpcException({ - code: 5, - message: 'User not found', - }); - } - } - throw new RpcException({}); - } - } -} diff --git a/.old/adapters/primaries/user.presenter.ts b/.old/adapters/primaries/user.presenter.ts deleted file mode 100644 index 6ff9a25..0000000 --- a/.old/adapters/primaries/user.presenter.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { AutoMap } from '@automapper/classes'; - -export class UserPresenter { - @AutoMap() - uuid: string; - - @AutoMap() - firstName: string; - - @AutoMap() - lastName: string; - - @AutoMap() - email: string; - - @AutoMap() - phone: string; -} diff --git a/.old/adapters/primaries/user.proto b/.old/adapters/primaries/user.proto deleted file mode 100644 index a579285..0000000 --- a/.old/adapters/primaries/user.proto +++ /dev/null @@ -1,35 +0,0 @@ -syntax = "proto3"; - -package user; - -service UsersService { - rpc FindOneByUuid(UserByUuid) returns (User); - rpc FindAll(UserFilter) returns (Users); - rpc Create(User) returns (User); - rpc Update(User) returns (User); - rpc Delete(UserByUuid) returns (Empty); -} - -message UserByUuid { - string uuid = 1; -} - -message User { - string uuid = 1; - string firstName = 2; - string lastName = 3; - string email = 4; - string phone = 5; -} - -message UserFilter { - optional int32 page = 1; - optional int32 perPage = 2; -} - -message Users { - repeated User data = 1; - int32 total = 2; -} - -message Empty {} diff --git a/.old/adapters/secondaries/message-publisher.ts b/.old/adapters/secondaries/message-publisher.ts deleted file mode 100644 index 2bb337a..0000000 --- a/.old/adapters/secondaries/message-publisher.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import { IPublishMessage } from '../../../../interfaces/message-publisher'; -import { MESSAGE_BROKER_PUBLISHER } from '../../../../app.constants'; -import { MessageBrokerPublisher } from '@mobicoop/message-broker-module'; - -@Injectable() -export class MessagePublisher implements IPublishMessage { - constructor( - @Inject(MESSAGE_BROKER_PUBLISHER) - private readonly messageBrokerPublisher: MessageBrokerPublisher, - ) {} - - publish = (routingKey: string, message: string): void => { - this.messageBrokerPublisher.publish(routingKey, message); - }; -} diff --git a/.old/adapters/secondaries/users.repository.ts b/.old/adapters/secondaries/users.repository.ts deleted file mode 100644 index 72d047f..0000000 --- a/.old/adapters/secondaries/users.repository.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { UserRepository } from '../../../database/domain/user-repository'; -import { User } from '../../domain/entities/user'; - -@Injectable() -export class UsersRepository extends UserRepository { - protected model = 'user'; -} diff --git a/.old/commands/create-user.command.ts b/.old/commands/create-user.command.ts deleted file mode 100644 index 70444d5..0000000 --- a/.old/commands/create-user.command.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { CreateUserRequest } from '../domain/dtos/create-user.request'; - -export class CreateUserCommand { - readonly createUserRequest: CreateUserRequest; - - constructor(request: CreateUserRequest) { - this.createUserRequest = request; - } -} diff --git a/.old/commands/delete-user.command.ts b/.old/commands/delete-user.command.ts deleted file mode 100644 index 2e69a67..0000000 --- a/.old/commands/delete-user.command.ts +++ /dev/null @@ -1,7 +0,0 @@ -export class DeleteUserCommand { - readonly uuid: string; - - constructor(uuid: string) { - this.uuid = uuid; - } -} diff --git a/.old/commands/update-user.command.ts b/.old/commands/update-user.command.ts deleted file mode 100644 index a65617f..0000000 --- a/.old/commands/update-user.command.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { UpdateUserRequest } from '../domain/dtos/update-user.request'; - -export class UpdateUserCommand { - readonly updateUserRequest: UpdateUserRequest; - - constructor(request: UpdateUserRequest) { - this.updateUserRequest = request; - } -} diff --git a/.old/domain/dtos/create-user.request.ts b/.old/domain/dtos/create-user.request.ts deleted file mode 100644 index 5071326..0000000 --- a/.old/domain/dtos/create-user.request.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { AutoMap } from '@automapper/classes'; -import { IsEmail, IsOptional, IsPhoneNumber, IsString } from 'class-validator'; - -export class CreateUserRequest { - @IsString() - @IsOptional() - @AutoMap() - uuid?: string; - - @IsString() - @IsOptional() - @AutoMap() - firstName?: string; - - @IsString() - @IsOptional() - @AutoMap() - lastName?: string; - - @IsEmail() - @IsOptional() - @AutoMap() - email?: string; - - @IsPhoneNumber() - @IsOptional() - @AutoMap() - phone?: string; -} diff --git a/.old/domain/dtos/find-all-users.request.ts b/.old/domain/dtos/find-all-users.request.ts deleted file mode 100644 index d01f8e0..0000000 --- a/.old/domain/dtos/find-all-users.request.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { IsInt, IsOptional } from 'class-validator'; - -export class FindAllUsersRequest { - @IsInt() - @IsOptional() - page?: number; - - @IsInt() - @IsOptional() - perPage?: number; -} diff --git a/.old/domain/dtos/find-user-by-uuid.request.ts b/.old/domain/dtos/find-user-by-uuid.request.ts deleted file mode 100644 index 2e2a70a..0000000 --- a/.old/domain/dtos/find-user-by-uuid.request.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { IsNotEmpty, IsString } from 'class-validator'; - -export class FindUserByUuidRequest { - @IsString() - @IsNotEmpty() - uuid: string; -} diff --git a/.old/domain/dtos/update-user.request.ts b/.old/domain/dtos/update-user.request.ts deleted file mode 100644 index 07eccaa..0000000 --- a/.old/domain/dtos/update-user.request.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { AutoMap } from '@automapper/classes'; -import { - IsEmail, - IsNotEmpty, - IsOptional, - IsPhoneNumber, - IsString, -} from 'class-validator'; - -export class UpdateUserRequest { - @IsString() - @IsNotEmpty() - @AutoMap() - uuid: string; - - @IsString() - @IsOptional() - @AutoMap() - firstName?: string; - - @IsString() - @IsOptional() - @AutoMap() - lastName?: string; - - @IsEmail() - @IsOptional() - @AutoMap() - email?: string; - - @IsPhoneNumber() - @IsOptional() - @AutoMap() - phone?: string; -} diff --git a/.old/domain/entities/user.ts b/.old/domain/entities/user.ts deleted file mode 100644 index 77f7720..0000000 --- a/.old/domain/entities/user.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { AutoMap } from '@automapper/classes'; - -export class User { - @AutoMap() - uuid: string; - - @AutoMap() - firstName?: string; - - @AutoMap() - lastName?: string; - - @AutoMap() - email?: string; - - @AutoMap() - phone?: string; -} diff --git a/.old/domain/usecases/create-user.usecase.ts b/.old/domain/usecases/create-user.usecase.ts deleted file mode 100644 index 273bb37..0000000 --- a/.old/domain/usecases/create-user.usecase.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Mapper } from '@automapper/core'; -import { InjectMapper } from '@automapper/nestjs'; -import { CommandHandler } from '@nestjs/cqrs'; -import { UsersRepository } from '../../adapters/secondaries/users.repository'; -import { CreateUserCommand } from '../../commands/create-user.command'; -import { CreateUserRequest } from '../dtos/create-user.request'; -import { User } from '../entities/user'; -import { Inject } from '@nestjs/common'; -import { MESSAGE_PUBLISHER } from '../../../../app.constants'; -import { IPublishMessage } from '../../../../interfaces/message-publisher'; - -@CommandHandler(CreateUserCommand) -export class CreateUserUseCase { - constructor( - private readonly repository: UsersRepository, - @Inject(MESSAGE_PUBLISHER) - private readonly messagePublisher: IPublishMessage, - @InjectMapper() private readonly mapper: Mapper, - ) {} - - execute = async (command: CreateUserCommand): Promise => { - const entity = this.mapper.map( - command.createUserRequest, - CreateUserRequest, - User, - ); - - try { - const user = await this.repository.create(entity); - this.messagePublisher.publish('user.create', JSON.stringify(user)); - this.messagePublisher.publish( - 'logging.user.create.info', - JSON.stringify(user), - ); - return user; - } catch (error) { - let key = 'logging.user.create.crit'; - if (error.message.includes('Already exists')) { - key = 'logging.user.create.warning'; - } - this.messagePublisher.publish( - key, - JSON.stringify({ - command, - error, - }), - ); - throw error; - } - }; -} diff --git a/.old/domain/usecases/delete-user.usecase.ts b/.old/domain/usecases/delete-user.usecase.ts deleted file mode 100644 index 3327419..0000000 --- a/.old/domain/usecases/delete-user.usecase.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { CommandHandler } from '@nestjs/cqrs'; -import { UsersRepository } from '../../adapters/secondaries/users.repository'; -import { DeleteUserCommand } from '../../commands/delete-user.command'; -import { User } from '../entities/user'; -import { IPublishMessage } from '../../../../interfaces/message-publisher'; -import { Inject } from '@nestjs/common'; -import { MESSAGE_PUBLISHER } from '../../../../app.constants'; - -@CommandHandler(DeleteUserCommand) -export class DeleteUserUseCase { - constructor( - private readonly repository: UsersRepository, - @Inject(MESSAGE_PUBLISHER) - private readonly messagePublisher: IPublishMessage, - ) {} - - execute = async (command: DeleteUserCommand): Promise => { - try { - const user = await this.repository.delete(command.uuid); - this.messagePublisher.publish( - 'user.delete', - JSON.stringify({ uuid: user.uuid }), - ); - this.messagePublisher.publish( - 'logging.user.delete.info', - JSON.stringify({ uuid: user.uuid }), - ); - return user; - } catch (error) { - this.messagePublisher.publish( - 'logging.user.delete.crit', - JSON.stringify({ - command, - error, - }), - ); - throw error; - } - }; -} diff --git a/.old/domain/usecases/find-all-users.usecase.ts b/.old/domain/usecases/find-all-users.usecase.ts deleted file mode 100644 index 99b18b1..0000000 --- a/.old/domain/usecases/find-all-users.usecase.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { QueryHandler } from '@nestjs/cqrs'; -import { ICollection } from 'src/modules/database/interfaces/collection.interface'; -import { UsersRepository } from '../../adapters/secondaries/users.repository'; -import { FindAllUsersQuery } from '../../queries/find-all-users.query'; -import { User } from '../entities/user'; - -@QueryHandler(FindAllUsersQuery) -export class FindAllUsersUseCase { - constructor(private readonly repository: UsersRepository) {} - - execute = async ( - findAllUsersQuery: FindAllUsersQuery, - ): Promise> => - this.repository.findAll(findAllUsersQuery.page, findAllUsersQuery.perPage); -} diff --git a/.old/domain/usecases/find-user-by-uuid.usecase.ts b/.old/domain/usecases/find-user-by-uuid.usecase.ts deleted file mode 100644 index 26d9944..0000000 --- a/.old/domain/usecases/find-user-by-uuid.usecase.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Inject, NotFoundException } from '@nestjs/common'; -import { QueryHandler } from '@nestjs/cqrs'; -import { UsersRepository } from '../../adapters/secondaries/users.repository'; -import { FindUserByUuidQuery } from '../../queries/find-user-by-uuid.query'; -import { User } from '../entities/user'; -import { MESSAGE_PUBLISHER } from '../../../../app.constants'; -import { IPublishMessage } from '../../../../interfaces/message-publisher'; - -@QueryHandler(FindUserByUuidQuery) -export class FindUserByUuidUseCase { - constructor( - private readonly repository: UsersRepository, - @Inject(MESSAGE_PUBLISHER) - private readonly messagePublisher: IPublishMessage, - ) {} - - execute = async (findUserByUuid: FindUserByUuidQuery): Promise => { - try { - const user = await this.repository.findOneByUuid(findUserByUuid.uuid); - if (!user) throw new NotFoundException(); - return user; - } catch (error) { - this.messagePublisher.publish( - 'logging.user.read.warning', - JSON.stringify({ - query: findUserByUuid, - error, - }), - ); - throw error; - } - }; -} diff --git a/.old/domain/usecases/update-user.usecase.ts b/.old/domain/usecases/update-user.usecase.ts deleted file mode 100644 index d8900f5..0000000 --- a/.old/domain/usecases/update-user.usecase.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Mapper } from '@automapper/core'; -import { InjectMapper } from '@automapper/nestjs'; -import { CommandHandler } from '@nestjs/cqrs'; -import { UsersRepository } from '../../adapters/secondaries/users.repository'; -import { UpdateUserCommand } from '../../commands/update-user.command'; -import { UpdateUserRequest } from '../dtos/update-user.request'; -import { User } from '../entities/user'; -import { MESSAGE_PUBLISHER } from '../../../../app.constants'; -import { Inject } from '@nestjs/common'; -import { IPublishMessage } from '../../../../interfaces/message-publisher'; - -@CommandHandler(UpdateUserCommand) -export class UpdateUserUseCase { - constructor( - private readonly repository: UsersRepository, - @Inject(MESSAGE_PUBLISHER) - private readonly messagePublisher: IPublishMessage, - @InjectMapper() private readonly mapper: Mapper, - ) {} - - execute = async (command: UpdateUserCommand): Promise => { - const entity = this.mapper.map( - command.updateUserRequest, - UpdateUserRequest, - User, - ); - - try { - const user = await this.repository.update( - command.updateUserRequest.uuid, - entity, - ); - this.messagePublisher.publish( - 'user.update', - JSON.stringify(command.updateUserRequest), - ); - this.messagePublisher.publish( - 'logging.user.update.info', - JSON.stringify(command.updateUserRequest), - ); - return user; - } catch (error) { - this.messagePublisher.publish( - 'logging.user.update.crit', - JSON.stringify({ - command, - error, - }), - ); - throw error; - } - }; -} diff --git a/.old/mappers/user.profile.ts b/.old/mappers/user.profile.ts deleted file mode 100644 index 8247598..0000000 --- a/.old/mappers/user.profile.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { createMap, forMember, ignore, Mapper } from '@automapper/core'; -import { AutomapperProfile, InjectMapper } from '@automapper/nestjs'; -import { Injectable } from '@nestjs/common'; -import { UserPresenter } from '../adapters/primaries/user.presenter'; -import { CreateUserRequest } from '../domain/dtos/create-user.request'; -import { UpdateUserRequest } from '../domain/dtos/update-user.request'; -import { User } from '../domain/entities/user'; - -@Injectable() -export class UserProfile extends AutomapperProfile { - constructor(@InjectMapper() mapper: Mapper) { - super(mapper); - } - - override get profile() { - return (mapper) => { - createMap(mapper, User, UserPresenter); - - createMap(mapper, CreateUserRequest, User); - - createMap( - mapper, - UpdateUserRequest, - User, - forMember((dest) => dest.uuid, ignore()), - ); - }; - } -} diff --git a/.old/queries/find-all-users.query.ts b/.old/queries/find-all-users.query.ts deleted file mode 100644 index 66e5483..0000000 --- a/.old/queries/find-all-users.query.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { FindAllUsersRequest } from '../domain/dtos/find-all-users.request'; - -export class FindAllUsersQuery { - page: number; - perPage: number; - - constructor(findAllUsersRequest?: FindAllUsersRequest) { - this.page = findAllUsersRequest?.page ?? 1; - this.perPage = findAllUsersRequest?.perPage ?? 10; - } -} diff --git a/.old/queries/find-user-by-uuid.query.ts b/.old/queries/find-user-by-uuid.query.ts deleted file mode 100644 index 9afaf15..0000000 --- a/.old/queries/find-user-by-uuid.query.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { FindUserByUuidRequest } from '../domain/dtos/find-user-by-uuid.request'; - -export class FindUserByUuidQuery { - readonly uuid: string; - - constructor(findUserByUuidRequest: FindUserByUuidRequest) { - this.uuid = findUserByUuidRequest.uuid; - } -} diff --git a/.old/tests/unit/find-all-users.usecase.spec.ts b/.old/tests/unit/find-all-users.usecase.spec.ts deleted file mode 100644 index 37b0c3c..0000000 --- a/.old/tests/unit/find-all-users.usecase.spec.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { UsersRepository } from '../../adapters/secondaries/users.repository'; -import { FindAllUsersRequest } from '../../domain/dtos/find-all-users.request'; -import { FindAllUsersUseCase } from '../../domain/usecases/find-all-users.usecase'; -import { FindAllUsersQuery } from '../../queries/find-all-users.query'; - -const findAllUsersRequest: FindAllUsersRequest = new FindAllUsersRequest(); -findAllUsersRequest.page = 1; -findAllUsersRequest.perPage = 10; - -const findAllUsersQuery: FindAllUsersQuery = new FindAllUsersQuery( - findAllUsersRequest, -); - -const mockUsers = [ - { - uuid: 'bb281075-1b98-4456-89d6-c643d3044a91', - firstName: 'John', - lastName: 'Doe', - email: 'john.doe@email.com', - phone: '0601020304', - }, - { - uuid: 'bb281075-1b98-4456-89d6-c643d3044a92', - firstName: 'Jane', - lastName: 'Doe', - email: 'jane.doe@email.com', - phone: '0602030405', - }, - { - uuid: 'bb281075-1b98-4456-89d6-c643d3044a93', - firstName: 'Jimmy', - lastName: 'Doe', - email: 'jimmy.doe@email.com', - phone: '0603040506', - }, -]; - -const mockUsersRepository = { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - findAll: jest.fn().mockImplementation((query?: FindAllUsersQuery) => { - return Promise.resolve(mockUsers); - }), -}; - -describe('FindAllUsersUseCase', () => { - let findAllUsersUseCase: FindAllUsersUseCase; - - beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - { - provide: UsersRepository, - useValue: mockUsersRepository, - }, - FindAllUsersUseCase, - ], - }).compile(); - - findAllUsersUseCase = module.get(FindAllUsersUseCase); - }); - - it('should be defined', () => { - expect(findAllUsersUseCase).toBeDefined(); - }); - - describe('execute', () => { - it('should return an array filled with users', async () => { - const users = await findAllUsersUseCase.execute(findAllUsersQuery); - - expect(users).toBe(mockUsers); - }); - }); -}); diff --git a/.old/tests/unit/find-user-by-uuid.usecase.spec.ts b/.old/tests/unit/find-user-by-uuid.usecase.spec.ts deleted file mode 100644 index ce38266..0000000 --- a/.old/tests/unit/find-user-by-uuid.usecase.spec.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { NotFoundException } from '@nestjs/common'; -import { Test, TestingModule } from '@nestjs/testing'; -import { UsersRepository } from '../../adapters/secondaries/users.repository'; -import { FindUserByUuidRequest } from '../../domain/dtos/find-user-by-uuid.request'; -import { FindUserByUuidUseCase } from '../../domain/usecases/find-user-by-uuid.usecase'; -import { FindUserByUuidQuery } from '../../queries/find-user-by-uuid.query'; -import { MESSAGE_PUBLISHER } from '../../../../app.constants'; - -const mockUser = { - uuid: 'bb281075-1b98-4456-89d6-c643d3044a91', - firstName: 'John', - lastName: 'Doe', - email: 'john.doe@email.com', - phone: '0601020304', -}; - -const mockUserRepository = { - findOneByUuid: jest - .fn() - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .mockImplementationOnce((query?: FindUserByUuidQuery) => { - return Promise.resolve(mockUser); - }) - .mockImplementation(() => { - return Promise.resolve(undefined); - }), -}; - -const mockMessagePublisher = { - publish: jest.fn().mockImplementation(), -}; - -describe('FindUserByUuidUseCase', () => { - let findUserByUuidUseCase: FindUserByUuidUseCase; - - beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ - imports: [], - providers: [ - { - provide: UsersRepository, - useValue: mockUserRepository, - }, - { - provide: MESSAGE_PUBLISHER, - useValue: mockMessagePublisher, - }, - FindUserByUuidUseCase, - ], - }).compile(); - - findUserByUuidUseCase = module.get( - FindUserByUuidUseCase, - ); - }); - - it('should be defined', () => { - expect(findUserByUuidUseCase).toBeDefined(); - }); - - describe('execute', () => { - it('should return a user', async () => { - const findUserByUuidRequest: FindUserByUuidRequest = - new FindUserByUuidRequest(); - findUserByUuidRequest.uuid = 'bb281075-1b98-4456-89d6-c643d3044a91'; - const user = await findUserByUuidUseCase.execute( - new FindUserByUuidQuery(findUserByUuidRequest), - ); - expect(user).toBe(mockUser); - }); - it('should throw an error if user does not exist', async () => { - const findUserByUuidRequest: FindUserByUuidRequest = - new FindUserByUuidRequest(); - findUserByUuidRequest.uuid = 'bb281075-1b98-4456-89d6-c643d3044a90'; - await expect( - findUserByUuidUseCase.execute( - new FindUserByUuidQuery(findUserByUuidRequest), - ), - ).rejects.toBeInstanceOf(NotFoundException); - }); - }); -}); diff --git a/package-lock.json b/package-lock.json index d9cf986..7bac676 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@grpc/proto-loader": "^0.7.4", "@liaoliaots/nestjs-redis": "^9.0.5", "@mobicoop/configuration-module": "^1.2.0", - "@mobicoop/ddd-library": "^0.3.0", + "@mobicoop/ddd-library": "file:../../packages/dddlibrary", "@mobicoop/health-module": "^2.0.0", "@mobicoop/message-broker-module": "^1.2.0", "@nestjs/cache-manager": "^1.0.0", @@ -60,8 +60,7 @@ }, "node_modules/@acuminous/bitsyntax": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@acuminous/bitsyntax/-/bitsyntax-0.1.2.tgz", - "integrity": "sha512-29lUK80d1muEQqiUsSo+3A0yP6CdspgC95EnKBMi22Xlwt79i/En4Vr67+cXhU+cZjbti3TgGGC5wy1stIywVQ==", + "license": "MIT", "dependencies": { "buffer-more-ints": "~1.0.0", "debug": "^4.3.4", @@ -73,9 +72,8 @@ }, "node_modules/@ampproject/remapping": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -86,9 +84,8 @@ }, "node_modules/@angular-devkit/core": { "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.0.1.tgz", - "integrity": "sha512-2uz98IqkKJlgnHbWQ7VeL4pb+snGAZXIama2KXi+k9GsRntdcw+udX8rL3G9SdUGUF+m6+147Y1oRBMHsO/v4w==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "8.12.0", "ajv-formats": "2.1.1", @@ -112,9 +109,8 @@ }, "node_modules/@angular-devkit/schematics": { "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.0.1.tgz", - "integrity": "sha512-A9D0LTYmiqiBa90GKcSuWb7hUouGIbm/AHbJbjL85WLLRbQA2PwKl7P5Mpd6nS/ZC0kfG4VQY3VOaDvb3qpI9g==", "dev": true, + "license": "MIT", "dependencies": { "@angular-devkit/core": "16.0.1", "jsonc-parser": "3.2.0", @@ -130,9 +126,8 @@ }, "node_modules/@angular-devkit/schematics-cli": { "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-16.0.1.tgz", - "integrity": "sha512-6KLA125dpgd6oJGtiO2JpZAb92uOG3njQGIt7NFcuQGW/5GO7J41vMXH9cBAfdtbV8SIggSmR/cIEE9ijfj6YQ==", "dev": true, + "license": "MIT", "dependencies": { "@angular-devkit/core": "16.0.1", "@angular-devkit/schematics": "16.0.1", @@ -152,9 +147,8 @@ }, "node_modules/@angular-devkit/schematics-cli/node_modules/inquirer": { "version": "8.2.4", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", - "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", "dev": true, + "license": "MIT", "dependencies": { "ansi-escapes": "^4.2.1", "chalk": "^4.1.1", @@ -178,9 +172,8 @@ }, "node_modules/@babel/code-frame": { "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", - "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/highlight": "^7.18.6" }, @@ -190,18 +183,16 @@ }, "node_modules/@babel/compat-data": { "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.3.tgz", - "integrity": "sha512-aNtko9OPOwVESUFp3MZfD8Uzxl7JzSeJpd7npIoxCasU37PFbAQRpKglkaKwlHOyeJdrREpo8TW8ldrkYWwvIQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.1.tgz", - "integrity": "sha512-Hkqu7J4ynysSXxmAahpN1jjRwVJ+NdpraFLIWflgjpVob3KNyK3/tIUc7Q7szed8WMp0JNa7Qtd1E9Oo22F9gA==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.21.4", @@ -229,18 +220,16 @@ }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/generator": { "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.3.tgz", - "integrity": "sha512-C17MW4wlk//ES/CJDL51kPNwl+qiBQyN7b9SKyVp11BLGFeSPoVaHrv+MNt8jwQFhQWowW88z1eeBx3pFz9v8A==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.22.3", "@jridgewell/gen-mapping": "^0.3.2", @@ -253,9 +242,8 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.1.tgz", - "integrity": "sha512-Rqx13UM3yVB5q0D/KwQ8+SPfX/+Rnsy1Lw1k/UwOC4KC6qrzIQoY3lYnBu5EHKBlEHHcj0M0W8ltPSkD8rqfsQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/compat-data": "^7.22.0", "@babel/helper-validator-option": "^7.21.0", @@ -272,36 +260,32 @@ }, "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/helper-environment-visitor": { "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.1.tgz", - "integrity": "sha512-Z2tgopurB/kTbidvzeBrc2To3PUP/9i5MUe+fU6QJCQDyPwSH2oRapkLw3KGECDYSjhQZCNxEvNvZlLw8JjGwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.20.7", "@babel/types": "^7.21.0" @@ -312,9 +296,8 @@ }, "node_modules/@babel/helper-hoist-variables": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -324,9 +307,8 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", - "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.21.4" }, @@ -336,9 +318,8 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.1.tgz", - "integrity": "sha512-dxAe9E7ySDGbQdCVOY/4+UcD8M9ZFqZcZhSPsPacvCG4M+9lwtDDQfI2EoaSvmf7W/8yCBkGU0m7Pvt1ru3UZw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.22.1", "@babel/helper-module-imports": "^7.21.4", @@ -355,18 +336,16 @@ }, "node_modules/@babel/helper-plugin-utils": { "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.21.5.tgz", - "integrity": "sha512-0WDaIlXKOX/3KfBK/dwP1oQGiPh6rjMkT7HIRv7i5RR2VUMwrx5ZL0dwBkKx7+SW1zwNdgjHd34IMk5ZjTeHVg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz", - "integrity": "sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.21.5" }, @@ -376,9 +355,8 @@ }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -388,36 +366,32 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz", - "integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.3.tgz", - "integrity": "sha512-jBJ7jWblbgr7r6wYZHMdIqKc73ycaTcCaWRq4/2LpuPHcx7xMlZvpGQkOYc9HeSjn6rcx15CPlgVcBtZ4WZJ2w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.21.9", "@babel/traverse": "^7.22.1", @@ -429,9 +403,8 @@ }, "node_modules/@babel/highlight": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", @@ -443,9 +416,8 @@ }, "node_modules/@babel/highlight/node_modules/ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -455,9 +427,8 @@ }, "node_modules/@babel/highlight/node_modules/chalk": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -469,42 +440,37 @@ }, "node_modules/@babel/highlight/node_modules/color-convert": { "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/supports-color": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -514,9 +480,8 @@ }, "node_modules/@babel/parser": { "version": "7.22.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.4.tgz", - "integrity": "sha512-VLLsx06XkEYqBtE5YGPwfSGwfrjnyPP5oiGty3S8pQLFDFLaS8VwWSIxkTXpcvr5zeYLE6+MBNl2npl/YnfofA==", "dev": true, + "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -526,9 +491,8 @@ }, "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -538,9 +502,8 @@ }, "node_modules/@babel/plugin-syntax-bigint": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -550,9 +513,8 @@ }, "node_modules/@babel/plugin-syntax-class-properties": { "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -562,9 +524,8 @@ }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -574,9 +535,8 @@ }, "node_modules/@babel/plugin-syntax-json-strings": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -586,9 +546,8 @@ }, "node_modules/@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -598,9 +557,8 @@ }, "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -610,9 +568,8 @@ }, "node_modules/@babel/plugin-syntax-numeric-separator": { "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -622,9 +579,8 @@ }, "node_modules/@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -634,9 +590,8 @@ }, "node_modules/@babel/plugin-syntax-optional-catch-binding": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -646,9 +601,8 @@ }, "node_modules/@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -658,9 +612,8 @@ }, "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -673,9 +626,8 @@ }, "node_modules/@babel/plugin-syntax-typescript": { "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.21.4.tgz", - "integrity": "sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.20.2" }, @@ -688,9 +640,8 @@ }, "node_modules/@babel/template": { "version": "7.21.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.21.9.tgz", - "integrity": "sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.21.4", "@babel/parser": "^7.21.9", @@ -702,9 +653,8 @@ }, "node_modules/@babel/traverse": { "version": "7.22.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.4.tgz", - "integrity": "sha512-Tn1pDsjIcI+JcLKq1AVlZEr4226gpuAQTsLMorsYg9tuS/kG7nuwwJ4AB8jfQuEgb/COBwR/DqJxmoiYFu5/rQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.21.4", "@babel/generator": "^7.22.3", @@ -723,18 +673,16 @@ }, "node_modules/@babel/traverse/node_modules/globals": { "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/types": { "version": "7.22.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.4.tgz", - "integrity": "sha512-Tx9x3UBHTTsMSW85WB2kphxYQVvrZ/t1FxD88IpSgIjiUJlCm9z+xWIDwyo1vffTwSqteqyznB8ZE9vYYk16zA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.21.5", "@babel/helper-validator-identifier": "^7.19.1", @@ -746,15 +694,13 @@ }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@colors/colors": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.1.90" @@ -762,9 +708,8 @@ }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -774,9 +719,8 @@ }, "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -784,8 +728,7 @@ }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -798,16 +741,14 @@ }, "node_modules/@eslint-community/regexpp": { "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -828,8 +769,7 @@ }, "node_modules/@eslint/eslintrc/node_modules/ajv": { "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -843,37 +783,32 @@ }, "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "license": "MIT" }, "node_modules/@eslint/js": { "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", - "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@golevelup/nestjs-common": { "version": "1.4.4", - "resolved": "https://registry.npmjs.org/@golevelup/nestjs-common/-/nestjs-common-1.4.4.tgz", - "integrity": "sha512-NTjtOhHTMuGwiR3lmBQKKaRr++mHQEsh8AxtaH+/EWOYKMK2Cv/8duaH9MQ0hI3TwnouyaA5IRxYR1ZCUyNXOQ==", + "license": "MIT", "dependencies": { "nanoid": "^3.2.0" } }, "node_modules/@golevelup/nestjs-discovery": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@golevelup/nestjs-discovery/-/nestjs-discovery-3.0.0.tgz", - "integrity": "sha512-ZvkXtobTKxXB1LJanP/l6Z/Fing88IMBr3uabQpU2IWjfsstjh02qYDSU2cfD6CSmNldX5ewW5Pd+SdK2lU8Sw==", + "license": "MIT", "dependencies": { "lodash": "^4.17.15" } }, "node_modules/@golevelup/nestjs-modules": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@golevelup/nestjs-modules/-/nestjs-modules-0.6.1.tgz", - "integrity": "sha512-E0STg8In8fhIivnGDJAA70+XLPHzK5bMTkCnif9FbZ8waTYDQ3T/QQL0h73k+CUFeznn1hmuEW14sNaE+8cd7w==", + "license": "MIT", "dependencies": { "lodash": "^4.17.21" }, @@ -884,8 +819,7 @@ }, "node_modules/@golevelup/nestjs-rabbitmq": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@golevelup/nestjs-rabbitmq/-/nestjs-rabbitmq-3.6.0.tgz", - "integrity": "sha512-gfa+27QlQdf49g9Y1JrFp/xXFjzXEtRTlVDW7KqJTUYqq03f2AKYdOPH0Iu8ScqpPPRt+qNv9COBJD44Sizerg==", + "license": "MIT", "dependencies": { "@golevelup/nestjs-common": "^1.4.4", "@golevelup/nestjs-discovery": "^3.0.0", @@ -896,8 +830,7 @@ }, "node_modules/@golevelup/nestjs-rabbitmq/node_modules/amqplib": { "version": "0.8.0", - "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.8.0.tgz", - "integrity": "sha512-icU+a4kkq4Y1PS4NNi+YPDMwdlbFcZ1EZTQT2nigW3fvOb6AOgUQ9+Mk4ue0Zu5cBg/XpDzB40oH10ysrk2dmA==", + "license": "MIT", "dependencies": { "bitsyntax": "~0.1.0", "bluebird": "^3.7.2", @@ -912,8 +845,6 @@ }, "node_modules/@golevelup/nestjs-rabbitmq/node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -927,12 +858,12 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/@grpc/grpc-js": { "version": "1.8.14", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.14.tgz", - "integrity": "sha512-w84maJ6CKl5aApCMzFll0hxtFNT6or9WwMslobKaqWUEf1K+zhlL43bSQhFreyYWIWR+Z0xnVFC1KtLm4ZpM/A==", + "license": "Apache-2.0", "dependencies": { "@grpc/proto-loader": "^0.7.0", "@types/node": ">=12.12.47" @@ -943,8 +874,7 @@ }, "node_modules/@grpc/proto-loader": { "version": "0.7.7", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.7.tgz", - "integrity": "sha512-1TIeXOi8TuSCQprPItwoMymZXxWT0CPxUhkrkeCUH+D8U7QDwQ6b7SUz2MaLuWM2llT+J/TVFLmQI5KtML3BhQ==", + "license": "Apache-2.0", "dependencies": { "@types/long": "^4.0.1", "lodash.camelcase": "^4.3.0", @@ -961,8 +891,7 @@ }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "license": "Apache-2.0", "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", @@ -974,8 +903,7 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -986,19 +914,16 @@ }, "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==" + "license": "BSD-3-Clause" }, "node_modules/@ioredis/commands": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", - "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" + "license": "MIT" }, "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", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, + "license": "ISC", "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -1012,27 +937,24 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, + "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -1043,9 +965,8 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -1056,9 +977,8 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -1068,9 +988,8 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -1083,9 +1002,8 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -1095,27 +1013,24 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@jest/console": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", - "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -1130,9 +1045,8 @@ }, "node_modules/@jest/console/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -1142,9 +1056,8 @@ }, "node_modules/@jest/console/node_modules/jest-message-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", - "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^28.1.3", @@ -1162,9 +1075,8 @@ }, "node_modules/@jest/console/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -1179,9 +1091,8 @@ }, "node_modules/@jest/console/node_modules/pretty-format": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", @@ -1194,9 +1105,8 @@ }, "node_modules/@jest/core": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.1.3.tgz", - "integrity": "sha512-CIKBrlaKOzA7YG19BEqCw3SLIsEwjZkeJzf5bdooVnW4bH5cktqe3JX+G2YV1aK5vP8N9na1IGWFzYaTp6k6NA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^28.1.3", "@jest/reporters": "^28.1.3", @@ -1242,9 +1152,8 @@ }, "node_modules/@jest/core/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -1254,9 +1163,8 @@ }, "node_modules/@jest/core/node_modules/jest-message-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", - "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^28.1.3", @@ -1274,9 +1182,8 @@ }, "node_modules/@jest/core/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -1291,9 +1198,8 @@ }, "node_modules/@jest/core/node_modules/pretty-format": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", @@ -1306,9 +1212,8 @@ }, "node_modules/@jest/core/node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -1321,9 +1226,8 @@ }, "node_modules/@jest/environment": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-28.1.3.tgz", - "integrity": "sha512-1bf40cMFTEkKyEf585R9Iz1WayDjHoHqvts0XFYEqyKM3cFWDpeMoqKKTAF9LSYQModPUlh8FKptoM2YcMWAXA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/fake-timers": "^28.1.3", "@jest/types": "^28.1.3", @@ -1336,9 +1240,8 @@ }, "node_modules/@jest/expect": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-28.1.3.tgz", - "integrity": "sha512-lzc8CpUbSoE4dqT0U+g1qODQjBRHPpCPXissXD4mS9+sWQdmmpeJ9zSH1rS1HEkrsMN0fb7nKrJ9giAR1d3wBw==", "dev": true, + "license": "MIT", "dependencies": { "expect": "^28.1.3", "jest-snapshot": "^28.1.3" @@ -1349,9 +1252,8 @@ }, "node_modules/@jest/expect-utils": { "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", "dev": true, + "license": "MIT", "dependencies": { "jest-get-type": "^29.4.3" }, @@ -1361,9 +1263,8 @@ }, "node_modules/@jest/expect/node_modules/@jest/expect-utils": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-28.1.3.tgz", - "integrity": "sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA==", "dev": true, + "license": "MIT", "dependencies": { "jest-get-type": "^28.0.2" }, @@ -1373,9 +1274,8 @@ }, "node_modules/@jest/expect/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -1385,18 +1285,16 @@ }, "node_modules/@jest/expect/node_modules/diff-sequences": { "version": "28.1.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", - "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", "dev": true, + "license": "MIT", "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, "node_modules/@jest/expect/node_modules/expect": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/expect/-/expect-28.1.3.tgz", - "integrity": "sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g==", "dev": true, + "license": "MIT", "dependencies": { "@jest/expect-utils": "^28.1.3", "jest-get-type": "^28.0.2", @@ -1410,9 +1308,8 @@ }, "node_modules/@jest/expect/node_modules/jest-diff": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", - "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^28.1.1", @@ -1425,18 +1322,16 @@ }, "node_modules/@jest/expect/node_modules/jest-get-type": { "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, "node_modules/@jest/expect/node_modules/jest-matcher-utils": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", - "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "jest-diff": "^28.1.3", @@ -1449,9 +1344,8 @@ }, "node_modules/@jest/expect/node_modules/jest-message-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", - "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^28.1.3", @@ -1469,9 +1363,8 @@ }, "node_modules/@jest/expect/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -1486,9 +1379,8 @@ }, "node_modules/@jest/expect/node_modules/pretty-format": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", @@ -1501,9 +1393,8 @@ }, "node_modules/@jest/fake-timers": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-28.1.3.tgz", - "integrity": "sha512-D/wOkL2POHv52h+ok5Oj/1gOG9HSywdoPtFsRCUmlCILXNn5eIWmcnd3DIiWlJnpGvQtmajqBP95Ei0EimxfLw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@sinonjs/fake-timers": "^9.1.2", @@ -1518,9 +1409,8 @@ }, "node_modules/@jest/fake-timers/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -1530,9 +1420,8 @@ }, "node_modules/@jest/fake-timers/node_modules/jest-message-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", - "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^28.1.3", @@ -1550,9 +1439,8 @@ }, "node_modules/@jest/fake-timers/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -1567,9 +1455,8 @@ }, "node_modules/@jest/fake-timers/node_modules/pretty-format": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", @@ -1582,9 +1469,8 @@ }, "node_modules/@jest/globals": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-28.1.3.tgz", - "integrity": "sha512-XFU4P4phyryCXu1pbcqMO0GSQcYe1IsalYCDzRNyhetyeyxMcIxa11qPNDpVNLeretItNqEmYYQn1UYz/5x1NA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^28.1.3", "@jest/expect": "^28.1.3", @@ -1596,9 +1482,8 @@ }, "node_modules/@jest/reporters": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.1.3.tgz", - "integrity": "sha512-JuAy7wkxQZVNU/V6g9xKzCGC5LVXx9FDcABKsSXp5MiKPEE2144a/vXTEDoyzjUpZKfVwp08Wqg5A4WfTMAzjg==", "dev": true, + "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^28.1.3", @@ -1640,9 +1525,8 @@ }, "node_modules/@jest/reporters/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -1652,9 +1536,8 @@ }, "node_modules/@jest/reporters/node_modules/jest-message-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", - "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^28.1.3", @@ -1672,9 +1555,8 @@ }, "node_modules/@jest/reporters/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -1689,9 +1571,8 @@ }, "node_modules/@jest/reporters/node_modules/pretty-format": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", @@ -1704,9 +1585,8 @@ }, "node_modules/@jest/schemas": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", - "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", "dev": true, + "license": "MIT", "dependencies": { "@sinclair/typebox": "^0.24.1" }, @@ -1716,9 +1596,8 @@ }, "node_modules/@jest/source-map": { "version": "28.1.2", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-28.1.2.tgz", - "integrity": "sha512-cV8Lx3BeStJb8ipPHnqVw/IM2VCMWO3crWZzYodSIkxXnRcXJipCdx1JCK0K5MsJJouZQTH73mzf4vgxRaH9ww==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.13", "callsites": "^3.0.0", @@ -1730,9 +1609,8 @@ }, "node_modules/@jest/test-result": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", - "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^28.1.3", "@jest/types": "^28.1.3", @@ -1745,9 +1623,8 @@ }, "node_modules/@jest/test-sequencer": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-28.1.3.tgz", - "integrity": "sha512-NIMPEqqa59MWnDi1kvXXpYbqsfQmSJsIbnd85mdVGkiDfQ9WQQTXOLsvISUfonmnBT+w85WEgneCigEEdHDFxw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/test-result": "^28.1.3", "graceful-fs": "^4.2.9", @@ -1760,9 +1637,8 @@ }, "node_modules/@jest/transform": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.1.3.tgz", - "integrity": "sha512-u5dT5di+oFI6hfcLOHGTAfmUxFRrjK+vnaP0kkVow9Md/M7V/MxqQMOz/VV25UZO8pzeA9PjfTpOu6BDuwSPQA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^28.1.3", @@ -1786,9 +1662,8 @@ }, "node_modules/@jest/transform/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -1803,9 +1678,8 @@ }, "node_modules/@jest/types": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", - "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^28.1.3", "@types/istanbul-lib-coverage": "^2.0.0", @@ -1820,9 +1694,8 @@ }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -1834,27 +1707,24 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/source-map": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz", - "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -1862,15 +1732,13 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" @@ -1878,14 +1746,12 @@ }, "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@liaoliaots/nestjs-redis": { "version": "9.0.5", - "resolved": "https://registry.npmjs.org/@liaoliaots/nestjs-redis/-/nestjs-redis-9.0.5.tgz", - "integrity": "sha512-nPcGLj0zW4mEsYtQYfWx3o7PmrMjuzFk6+t/g2IRopAeWWUZZ/5nIJ4KTKiz/3DJEUkbX8PZqB+dOhklGF0SVA==", + "license": "MIT", "dependencies": { "tslib": "2.4.1" }, @@ -1900,16 +1766,14 @@ }, "node_modules/@lukeed/csprng": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", - "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@mobicoop/configuration-module": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@mobicoop/configuration-module/-/configuration-module-1.2.0.tgz", - "integrity": "sha512-l0iDae7SgVVmjnCa2MBqAr3Er0yn4E7yiG8e7cs4XtNGUKrC1N0Ju56TEAraEYK9aZAZ36TCs06m1fep+rgwFA==", + "license": "AGPL", "dependencies": { "@golevelup/nestjs-rabbitmq": "^3.6.0", "@liaoliaots/nestjs-redis": "^9.0.5", @@ -1925,8 +1789,8 @@ }, "node_modules/@mobicoop/ddd-library": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@mobicoop/ddd-library/-/ddd-library-0.3.0.tgz", - "integrity": "sha512-MoUDqlrDmJkumCFSyW9FY2DLbguT4rytFrmBt9tVNCr2Es6nlz4Ml3HVBwJTZrlJFU79XmiUQ5WAO0MHJt+nAg==", + "resolved": "file:../../packages/dddlibrary", + "license": "AGPL", "dependencies": { "@nestjs/event-emitter": "^1.4.2", "@nestjs/microservices": "^9.4.0", @@ -1953,8 +1817,7 @@ }, "node_modules/@mobicoop/health-module": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@mobicoop/health-module/-/health-module-2.0.0.tgz", - "integrity": "sha512-r/7zrHJKVRTIiZ50ILy3lEUC/9vi6k0TRcYPMS8zcnUssQg+MPcT5DQS9B9tTB2gkKwcCyxOQlZZIppIybFX3A==", + "license": "AGPL", "dependencies": { "@grpc/grpc-js": "^1.8.14", "@grpc/proto-loader": "^0.7.7", @@ -1971,8 +1834,7 @@ }, "node_modules/@mobicoop/message-broker-module": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@mobicoop/message-broker-module/-/message-broker-module-1.2.0.tgz", - "integrity": "sha512-RoSHHK1GyQ/QVDmm3JS/wBfh171oChvyEp6YWmJd12krFLrPVn9MoEvZdyT3I5J31oBiUabMPle5Kdpw+Nrmww==", + "license": "AGPL", "dependencies": { "@golevelup/nestjs-rabbitmq": "^3.6.0", "@types/amqplib": "^0.10.1", @@ -1984,8 +1846,7 @@ }, "node_modules/@nestjs/axios": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.0.0.tgz", - "integrity": "sha512-ULdH03jDWkS5dy9X69XbUVbhC+0pVnrRcj7bIK/ytTZ76w7CgvTZDJqsIyisg3kNOiljRW/4NIjSf3j6YGvl+g==", + "license": "MIT", "peerDependencies": { "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", "axios": "^1.3.1", @@ -1995,8 +1856,7 @@ }, "node_modules/@nestjs/cache-manager": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/cache-manager/-/cache-manager-1.0.0.tgz", - "integrity": "sha512-XMNdgsj3H+Ng/SYwFl13vRGNFA3e5Obk8LNwIuHLVSocnK2exReAWtscxEjQhoBc4FW4jAYOgU/U+mt18Q9T0g==", + "license": "MIT", "peerDependencies": { "@nestjs/common": "^9.0.0", "cache-manager": "<=5", @@ -2006,9 +1866,8 @@ }, "node_modules/@nestjs/cli": { "version": "9.5.0", - "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-9.5.0.tgz", - "integrity": "sha512-Z7q+3vNsQSG2d2r2Hl/OOj5EpfjVx3OfnJ9+KuAsOdw1sKLm7+Zc6KbhMFTd/eIvfx82ww3Nk72xdmfPYCulWA==", "dev": true, + "license": "MIT", "dependencies": { "@angular-devkit/core": "16.0.1", "@angular-devkit/schematics": "16.0.1", @@ -2042,18 +1901,16 @@ }, "node_modules/@nestjs/cli/node_modules/strip-bom": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@nestjs/cli/node_modules/tsconfig-paths": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, + "license": "MIT", "dependencies": { "json5": "^2.2.2", "minimist": "^1.2.6", @@ -2065,9 +1922,8 @@ }, "node_modules/@nestjs/cli/node_modules/webpack": { "version": "5.82.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.82.1.tgz", - "integrity": "sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==", "dev": true, + "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.0", @@ -2112,8 +1968,7 @@ }, "node_modules/@nestjs/common": { "version": "9.4.2", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.4.2.tgz", - "integrity": "sha512-sea+qZnbD5x3YWZDVQT/wbVJ2NiABaM1tyZTLuW9hpkcM2KFA96xKtK3VaCxyz49zoXIgSOefsyK7HuUMCe27Q==", + "license": "MIT", "dependencies": { "iterare": "1.2.1", "tslib": "2.5.2", @@ -2144,13 +1999,11 @@ }, "node_modules/@nestjs/common/node_modules/tslib": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", - "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==" + "license": "0BSD" }, "node_modules/@nestjs/config": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-2.3.2.tgz", - "integrity": "sha512-VtGV8PBpxzMzz68kdxTWqPm9v7SYCSZXQ0tC72AMNnjdmU+CVjUSLpEpdnm0XcWHxE1nV6wSI3HZxsATIV4ZxA==", + "license": "MIT", "dependencies": { "dotenv": "16.0.3", "dotenv-expand": "10.0.0", @@ -2165,9 +2018,8 @@ }, "node_modules/@nestjs/core": { "version": "9.4.2", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-9.4.2.tgz", - "integrity": "sha512-S5K9GTpjBqEJtu5VxRsVaaGEBZ1bkY+Ht4+2hqZSKsI+rzcEB5hcvR+5KiMsMY1VGYvlZ99lxYz72p4h8B0mKw==", "hasInstallScript": true, + "license": "MIT", "dependencies": { "@nuxtjs/opencollective": "0.3.2", "fast-safe-stringify": "2.1.1", @@ -2202,13 +2054,11 @@ }, "node_modules/@nestjs/core/node_modules/tslib": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", - "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==" + "license": "0BSD" }, "node_modules/@nestjs/cqrs": { "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@nestjs/cqrs/-/cqrs-9.0.4.tgz", - "integrity": "sha512-nWDF+xs4jqs6OjxFg/wVSd0NiIV9+EFCJrJNTo4VRWe78CcAaitbp56CBspUh4gKyfkci95i+EhHdEqRXKFptg==", + "license": "MIT", "dependencies": { "uuid": "9.0.0" }, @@ -2221,8 +2071,7 @@ }, "node_modules/@nestjs/event-emitter": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/event-emitter/-/event-emitter-2.0.0.tgz", - "integrity": "sha512-fZRv3+PmqXcbqCDRXRWhKDa+v3gmPUq4x5sQE5reVlDtEaCoAXwtGrtNswPtqd0msjyo8OWZF9k1sFjeRL6Xag==", + "license": "MIT", "dependencies": { "eventemitter2": "6.4.9" }, @@ -2234,8 +2083,7 @@ }, "node_modules/@nestjs/microservices": { "version": "9.4.2", - "resolved": "https://registry.npmjs.org/@nestjs/microservices/-/microservices-9.4.2.tgz", - "integrity": "sha512-06VlJJS+QyyF5rS6WnMi6POdlGoEHEyvaOuySUm7QKfRILVUOqxcB6ANsKNNv2VPmRSLab/pYTpaQiEGazzRYA==", + "license": "MIT", "dependencies": { "iterare": "1.2.1", "tslib": "2.5.2" @@ -2291,13 +2139,11 @@ }, "node_modules/@nestjs/microservices/node_modules/tslib": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", - "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==" + "license": "0BSD" }, "node_modules/@nestjs/platform-express": { "version": "9.4.2", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-9.4.2.tgz", - "integrity": "sha512-FVSJmVH+kndcDjvUK7xUzE3AmtQwlcXKN2hwJolyyIS7WXs6Awyb78cJGr0w27ESKoVQeSKPVbom0sLJFG153A==", + "license": "MIT", "dependencies": { "body-parser": "1.20.2", "cors": "2.8.5", @@ -2316,14 +2162,12 @@ }, "node_modules/@nestjs/platform-express/node_modules/tslib": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", - "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==" + "license": "0BSD" }, "node_modules/@nestjs/schematics": { "version": "9.2.0", - "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.2.0.tgz", - "integrity": "sha512-wHpNJDPzM6XtZUOB3gW0J6mkFCSJilzCM3XrHI1o0C8vZmFE1snbmkIXNyoi1eV0Nxh1BMymcgz5vIMJgQtTqw==", "dev": true, + "license": "MIT", "dependencies": { "@angular-devkit/core": "16.0.1", "@angular-devkit/schematics": "16.0.1", @@ -2336,8 +2180,7 @@ }, "node_modules/@nestjs/terminus": { "version": "9.2.2", - "resolved": "https://registry.npmjs.org/@nestjs/terminus/-/terminus-9.2.2.tgz", - "integrity": "sha512-AWUA8XLcgxWUjUFYHDqi42M7CZn2e+DEWxP+MqNAbMzz4ybB5jGcFK5Fy8qwaNBoWg6KMF1JiXOOygGXgk9ydg==", + "license": "MIT", "dependencies": { "boxen": "5.1.2", "check-disk-space": "3.3.1" @@ -2401,9 +2244,8 @@ }, "node_modules/@nestjs/testing": { "version": "9.4.2", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-9.4.2.tgz", - "integrity": "sha512-4WZPJz85zLVZkhmWYq+Unr43MixISelg/TyuX1YFZYOeukIN+O6fRtAAPIKLqRQsiY0rE/h8FAEbYGWhNrRfSA==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "2.5.2" }, @@ -2428,14 +2270,12 @@ }, "node_modules/@nestjs/testing/node_modules/tslib": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", - "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==", - "dev": true + "dev": true, + "license": "0BSD" }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -2446,16 +2286,14 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -2466,8 +2304,7 @@ }, "node_modules/@nuxtjs/opencollective": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", - "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "consola": "^2.15.0", @@ -2483,9 +2320,8 @@ }, "node_modules/@prisma/client": { "version": "4.15.0", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.15.0.tgz", - "integrity": "sha512-xnROvyABcGiwqRNdrObHVZkD9EjkJYHOmVdlKy1yGgI+XOzvMzJ4tRg3dz1pUlsyhKxXGCnjIQjWW+2ur+YXuw==", "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { "@prisma/engines-version": "4.15.0-28.8fbc245156db7124f997f4cecdd8d1219e360944" }, @@ -2503,40 +2339,33 @@ }, "node_modules/@prisma/engines": { "version": "4.15.0", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.15.0.tgz", - "integrity": "sha512-FTaOCGs0LL0OW68juZlGxFtYviZa4xdQj/rQEdat2txw0s3Vu/saAPKjNVXfIgUsGXmQ72HPgNr6935/P8FNAA==", "devOptional": true, - "hasInstallScript": true + "hasInstallScript": true, + "license": "Apache-2.0" }, "node_modules/@prisma/engines-version": { "version": "4.15.0-28.8fbc245156db7124f997f4cecdd8d1219e360944", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.15.0-28.8fbc245156db7124f997f4cecdd8d1219e360944.tgz", - "integrity": "sha512-sVOig4tjGxxlYaFcXgE71f/rtFhzyYrfyfNFUsxCIEJyVKU9rdOWIlIwQ2NQ7PntvGnn+x0XuFo4OC1jvPJKzg==" + "license": "Apache-2.0" }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/base64": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/codegen": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/eventemitter": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/fetch": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" @@ -2544,90 +2373,76 @@ }, "node_modules/@protobufjs/float": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/inquire": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/path": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/pool": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/utf8": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + "license": "BSD-3-Clause" }, "node_modules/@sinclair/typebox": { "version": "0.24.51", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", - "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@sinonjs/commons": { "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", - "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^1.7.0" } }, "node_modules/@tsconfig/node10": { "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node16": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/amqplib": { "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.10.1.tgz", - "integrity": "sha512-j6ANKT79ncUDnAs/+9r9eDujxbeJoTjoVu33gHHcaPfmLQaMhvfbH2GqSe8KUM444epAp1Vl3peVOQfZk3UIqA==", + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/babel__core": { "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", - "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -2638,18 +2453,16 @@ }, "node_modules/@types/babel__generator": { "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__template": { "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" @@ -2657,23 +2470,20 @@ }, "node_modules/@types/babel__traverse": { "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", - "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.20.7" } }, "node_modules/@types/cookiejar": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==" + "license": "MIT" }, "node_modules/@types/eslint": { "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.40.0.tgz", - "integrity": "sha512-nbq2mvc/tBrK9zQQuItvjJl++GTN5j06DaPtp3hZCpngmG6Q3xoyEmd0TwZI0gAy/G1X0zhGBbr2imsGFdFV0g==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -2681,9 +2491,8 @@ }, "node_modules/@types/eslint-scope": { "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", "dev": true, + "license": "MIT", "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -2691,48 +2500,42 @@ }, "node_modules/@types/estree": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/graceful-fs": { "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", "dev": true, + "license": "MIT", "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "node_modules/@types/istanbul-reports": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", "dev": true, + "license": "MIT", "dependencies": { "@types/istanbul-lib-report": "*" } }, "node_modules/@types/jest": { "version": "29.5.2", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.2.tgz", - "integrity": "sha512-mSoZVJF5YzGVCk+FsDxzDuH7s+SCkzrgKZzf0Z0T2WudhBUPoF6ktoTPC4R0ZoCPCV5xUvuU6ias5NvxcBcMMg==", "dev": true, + "license": "MIT", "dependencies": { "expect": "^29.0.0", "pretty-format": "^29.0.0" @@ -2740,46 +2543,38 @@ }, "node_modules/@types/json-schema": { "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==" + "license": "MIT" }, "node_modules/@types/long": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", - "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + "license": "MIT" }, "node_modules/@types/node": { "version": "18.16.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.16.tgz", - "integrity": "sha512-NpaM49IGQQAUlBhHMF82QH80J08os4ZmyF9MkpCzWAGuOHqE4gTEbhzd7L3l5LmWuZ6E0OiC1FweQ4tsiW35+g==" + "license": "MIT" }, "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 + "dev": true, + "license": "MIT" }, "node_modules/@types/prettier": { "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/semver": { "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==" + "license": "MIT" }, "node_modules/@types/stack-utils": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/superagent": { "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.18.tgz", - "integrity": "sha512-LOWgpacIV8GHhrsQU+QMZuomfqXiqzz3ILLkCtKx3Us6AmomFViuzKT9D693QTKgyut2oCytMG8/efOop+DB+w==", + "license": "MIT", "dependencies": { "@types/cookiejar": "*", "@types/node": "*" @@ -2787,42 +2582,36 @@ }, "node_modules/@types/supertest": { "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.12.tgz", - "integrity": "sha512-X3HPWTwXRerBZS7Mo1k6vMVR1Z6zmJcDVn5O/31whe0tnjE4te6ZJSJGq1RiqHPjzPdMTfjCFogDJmwng9xHaQ==", + "license": "MIT", "dependencies": { "@types/superagent": "*" } }, "node_modules/@types/uuid": { "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", - "integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/validator": { "version": "13.7.17", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.17.tgz", - "integrity": "sha512-aqayTNmeWrZcvnG2MG9eGYI6b7S5fl+yKgPs6bAjOTwPS316R5SxBGKvtSExfyoJU7pIeHJfsHI0Ji41RVMkvQ==" + "license": "MIT" }, "node_modules/@types/yargs": { "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dev": true, + "license": "MIT", "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.59.8", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.8.tgz", - "integrity": "sha512-JDMOmhXteJ4WVKOiHXGCoB96ADWg9q7efPWHRViT/f09bA8XOMLAVHHju3l0MkZnG1izaWXYmgvQcUjTRcpShQ==", + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.4.0", "@typescript-eslint/scope-manager": "5.59.8", @@ -2854,8 +2643,7 @@ }, "node_modules/@typescript-eslint/parser": { "version": "5.59.8", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.8.tgz", - "integrity": "sha512-AnR19RjJcpjoeGojmwZtCwBX/RidqDZtzcbG3xHrmz0aHHoOcbWnpDllenRDmDvsV0RQ6+tbb09/kyc+UT9Orw==", + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/scope-manager": "5.59.8", "@typescript-eslint/types": "5.59.8", @@ -2880,8 +2668,7 @@ }, "node_modules/@typescript-eslint/scope-manager": { "version": "5.59.8", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.8.tgz", - "integrity": "sha512-/w08ndCYI8gxGf+9zKf1vtx/16y8MHrZs5/tnjHhMLNSixuNcJavSX4wAiPf4aS5x41Es9YPCn44MIe4cxIlig==", + "license": "MIT", "dependencies": { "@typescript-eslint/types": "5.59.8", "@typescript-eslint/visitor-keys": "5.59.8" @@ -2896,8 +2683,7 @@ }, "node_modules/@typescript-eslint/type-utils": { "version": "5.59.8", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.8.tgz", - "integrity": "sha512-+5M518uEIHFBy3FnyqZUF3BMP+AXnYn4oyH8RF012+e7/msMY98FhGL5SrN29NQ9xDgvqCgYnsOiKp1VjZ/fpA==", + "license": "MIT", "dependencies": { "@typescript-eslint/typescript-estree": "5.59.8", "@typescript-eslint/utils": "5.59.8", @@ -2922,8 +2708,7 @@ }, "node_modules/@typescript-eslint/types": { "version": "5.59.8", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.8.tgz", - "integrity": "sha512-+uWuOhBTj/L6awoWIg0BlWy0u9TyFpCHrAuQ5bNfxDaZ1Ppb3mx6tUigc74LHcbHpOHuOTOJrBoAnhdHdaea1w==", + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -2934,8 +2719,7 @@ }, "node_modules/@typescript-eslint/typescript-estree": { "version": "5.59.8", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.8.tgz", - "integrity": "sha512-Jy/lPSDJGNow14vYu6IrW790p7HIf/SOV1Bb6lZ7NUkLc2iB2Z9elESmsaUtLw8kVqogSbtLH9tut5GCX1RLDg==", + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "5.59.8", "@typescript-eslint/visitor-keys": "5.59.8", @@ -2960,8 +2744,7 @@ }, "node_modules/@typescript-eslint/utils": { "version": "5.59.8", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.8.tgz", - "integrity": "sha512-Tr65630KysnNn9f9G7ROF3w1b5/7f6QVCJ+WK9nhIocWmx9F+TmCAcglF26Vm7z8KCTwoKcNEBZrhlklla3CKg==", + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", @@ -2985,8 +2768,7 @@ }, "node_modules/@typescript-eslint/visitor-keys": { "version": "5.59.8", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.8.tgz", - "integrity": "sha512-pJhi2ms0x0xgloT7xYabil3SGGlojNNKjK/q6dB3Ey0uJLMjK2UDGJvHieiyJVW/7C3KI+Z4Q3pEHkm4ejA+xQ==", + "license": "MIT", "dependencies": { "@typescript-eslint/types": "5.59.8", "eslint-visitor-keys": "^3.3.0" @@ -3001,9 +2783,8 @@ }, "node_modules/@webassemblyjs/ast": { "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6" @@ -3011,27 +2792,23 @@ }, "node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -3040,15 +2817,13 @@ }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-buffer": "1.11.6", @@ -3058,33 +2833,29 @@ }, "node_modules/@webassemblyjs/ieee754": { "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "dev": true, + "license": "MIT", "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-buffer": "1.11.6", @@ -3098,9 +2869,8 @@ }, "node_modules/@webassemblyjs/wasm-gen": { "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", @@ -3111,9 +2881,8 @@ }, "node_modules/@webassemblyjs/wasm-opt": { "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-buffer": "1.11.6", @@ -3123,9 +2892,8 @@ }, "node_modules/@webassemblyjs/wasm-parser": { "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -3137,9 +2905,8 @@ }, "node_modules/@webassemblyjs/wast-printer": { "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.11.6", "@xtuc/long": "4.2.2" @@ -3147,20 +2914,17 @@ }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@xtuc/long": { "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/accepts": { "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -3171,8 +2935,7 @@ }, "node_modules/acorn": { "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -3182,35 +2945,31 @@ }, "node_modules/acorn-import-assertions": { "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^8" } }, "node_modules/acorn-jsx": { "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/acorn-walk": { "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/ajv": { "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -3224,9 +2983,8 @@ }, "node_modules/ajv-formats": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^8.0.0" }, @@ -3241,8 +2999,7 @@ }, "node_modules/amqp-connection-manager": { "version": "3.9.0", - "resolved": "https://registry.npmjs.org/amqp-connection-manager/-/amqp-connection-manager-3.9.0.tgz", - "integrity": "sha512-ZKw9ckJKz40Lc2pC7DY0NVocpzPalMaCgv0sBn+N4er2QFAJul9pIiMOm/FsPHeCzB+FulV7PckOpmZvWvewGQ==", + "license": "MIT", "dependencies": { "promise-breaker": "^5.0.0" }, @@ -3256,8 +3013,7 @@ }, "node_modules/amqplib": { "version": "0.10.3", - "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.10.3.tgz", - "integrity": "sha512-UHmuSa7n8vVW/a5HGh2nFPqAEr8+cD4dEZ6u9GjP91nHfr1a54RyAKyra7Sb5NH7NBKOUlyQSMXIp0qAixKexw==", + "license": "MIT", "dependencies": { "@acuminous/bitsyntax": "^0.1.2", "buffer-more-ints": "~1.0.0", @@ -3270,26 +3026,23 @@ }, "node_modules/ansi-align": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "license": "ISC", "dependencies": { "string-width": "^4.1.0" } }, "node_modules/ansi-colors": { "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/ansi-escapes": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.21.3" }, @@ -3302,9 +3055,8 @@ }, "node_modules/ansi-escapes/node_modules/type-fest": { "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -3314,16 +3066,14 @@ }, "node_modules/ansi-regex": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -3336,9 +3086,8 @@ }, "node_modules/anymatch": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -3349,48 +3098,40 @@ }, "node_modules/append-field": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + "license": "MIT" }, "node_modules/arg": { "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "license": "Python-2.0" }, "node_modules/array-flatten": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "license": "MIT" }, "node_modules/array-union": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/asap": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/asynckit": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "license": "MIT" }, "node_modules/axios": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -3399,9 +3140,8 @@ }, "node_modules/babel-jest": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.1.3.tgz", - "integrity": "sha512-epUaPOEWMk3cWX0M/sPvCHHCe9fMFAa/9hXEgKP8nFfNl/jlGkE9ucq9NqkZGXLDduCJYS0UvSlPUwC0S+rH6Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/transform": "^28.1.3", "@types/babel__core": "^7.1.14", @@ -3420,9 +3160,8 @@ }, "node_modules/babel-plugin-istanbul": { "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", @@ -3436,9 +3175,8 @@ }, "node_modules/babel-plugin-jest-hoist": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.3.tgz", - "integrity": "sha512-Ys3tUKAmfnkRUpPdpa98eYrAR0nV+sSFUZZEGuQ2EbFd1y4SOLtD5QDNHAq+bb9a+bbXvYQC4b+ID/THIMcU6Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", @@ -3451,9 +3189,8 @@ }, "node_modules/babel-preset-current-node-syntax": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", @@ -3474,9 +3211,8 @@ }, "node_modules/babel-preset-jest": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-28.1.3.tgz", - "integrity": "sha512-L+fupJvlWAHbQfn74coNX3zf60LXMJsezNvvx8eIh7iOR1luJ1poxYgQk1F8PYtNq/6QODDHCqsSnTFSWC491A==", "dev": true, + "license": "MIT", "dependencies": { "babel-plugin-jest-hoist": "^28.1.3", "babel-preset-current-node-syntax": "^1.0.0" @@ -3490,13 +3226,10 @@ }, "node_modules/balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "license": "MIT" }, "node_modules/base64-js": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true, "funding": [ { @@ -3511,21 +3244,20 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/binary-extensions": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/bitsyntax": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.1.0.tgz", - "integrity": "sha512-ikAdCnrloKmFOugAfxWws89/fPc+nw0OOG1IzIE72uSOg/A3cYptKCjSUhDTuj7fhsJtzkzlv7l3b8PzRHLN0Q==", + "license": "MIT", "dependencies": { "buffer-more-ints": "~1.0.0", "debug": "~2.6.9", @@ -3537,22 +3269,19 @@ }, "node_modules/bitsyntax/node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, "node_modules/bitsyntax/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "license": "MIT" }, "node_modules/bl": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, + "license": "MIT", "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -3561,9 +3290,8 @@ }, "node_modules/bl/node_modules/readable-stream": { "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -3575,8 +3303,6 @@ }, "node_modules/bl/node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { @@ -3591,26 +3317,24 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/bl/node_modules/string_decoder": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } }, "node_modules/bluebird": { "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + "license": "MIT" }, "node_modules/body-parser": { "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -3632,21 +3356,18 @@ }, "node_modules/body-parser/node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "license": "MIT" }, "node_modules/boxen": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "license": "MIT", "dependencies": { "ansi-align": "^3.0.0", "camelcase": "^6.2.0", @@ -3666,8 +3387,7 @@ }, "node_modules/brace-expansion": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3675,8 +3395,7 @@ }, "node_modules/braces": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "license": "MIT", "dependencies": { "fill-range": "^7.0.1" }, @@ -3686,8 +3405,6 @@ }, "node_modules/browserslist": { "version": "4.21.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.7.tgz", - "integrity": "sha512-BauCXrQ7I2ftSqd2mvKHGo85XR0u7Ru3C/Hxsy/0TkfCtjrmAbPdzLGasmoiBxplpDXlPvdjX9u7srIMfgasNA==", "dev": true, "funding": [ { @@ -3703,6 +3420,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "caniuse-lite": "^1.0.30001489", "electron-to-chromium": "^1.4.411", @@ -3718,9 +3436,8 @@ }, "node_modules/bs-logger": { "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", "dev": true, + "license": "MIT", "dependencies": { "fast-json-stable-stringify": "2.x" }, @@ -3730,17 +3447,14 @@ }, "node_modules/bser": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "node-int64": "^0.4.0" } }, "node_modules/buffer": { "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, "funding": [ { @@ -3756,6 +3470,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -3763,18 +3478,14 @@ }, "node_modules/buffer-from": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "license": "MIT" }, "node_modules/buffer-more-ints": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", - "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==" + "license": "MIT" }, "node_modules/busboy": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", "dependencies": { "streamsearch": "^1.1.0" }, @@ -3784,16 +3495,14 @@ }, "node_modules/bytes": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/cache-manager": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-5.2.1.tgz", - "integrity": "sha512-qYHx0DlM0mepUqXkpDg83K1dYEXOinq9+sYdHxs1c5LQjR1MPgm34im+JVtsy9+uoeE2T1JLzJSAB+nV4IH5dQ==", + "license": "MIT", "dependencies": { "lodash.clonedeep": "^4.5.0", "lru-cache": "~9.1.1" @@ -3801,8 +3510,7 @@ }, "node_modules/cache-manager-ioredis-yet": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cache-manager-ioredis-yet/-/cache-manager-ioredis-yet-1.1.0.tgz", - "integrity": "sha512-bGBAq8oNzzNkO2dwlYGWBxNXrz4w8FUTpe3nfUydJ6bm1ixKEcSUKYksGokQMaRgqkQjMbIHWFkvb8p+V9ZKqw==", + "license": "MIT", "dependencies": { "cache-manager": "^5.1.0", "ioredis": "^5.2.3" @@ -3813,8 +3521,7 @@ }, "node_modules/call-bind": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -3825,16 +3532,14 @@ }, "node_modules/callsites": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/camelcase": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -3844,8 +3549,6 @@ }, "node_modules/caniuse-lite": { "version": "1.0.30001492", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001492.tgz", - "integrity": "sha512-2efF8SAZwgAX1FJr87KWhvuJxnGJKOnctQa8xLOskAXNXq8oiuqgl6u1kk3fFpsp3GgvzlRjiK1sl63hNtFADw==", "dev": true, "funding": [ { @@ -3860,12 +3563,12 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -3879,31 +3582,26 @@ }, "node_modules/char-regex": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/chardet": { "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/check-disk-space": { "version": "3.3.1", - "resolved": "https://registry.npmjs.org/check-disk-space/-/check-disk-space-3.3.1.tgz", - "integrity": "sha512-iOrT8yCZjSnyNZ43476FE2rnssvgw5hnuwOM0hm8Nj1qa0v4ieUUEbCyxxsEliaoDUb/75yCOL71zkDiDBLbMQ==", + "license": "MIT", "engines": { "node": ">=12" } }, "node_modules/chokidar": { "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "funding": [ { @@ -3911,6 +3609,7 @@ "url": "https://paulmillr.com/funding/" } ], + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -3929,17 +3628,14 @@ }, "node_modules/chrome-trace-event": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0" } }, "node_modules/ci-info": { "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", "dev": true, "funding": [ { @@ -3947,25 +3643,23 @@ "url": "https://github.com/sponsors/sibiraj-s" } ], + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/cjs-module-lexer": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/class-transformer": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", - "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" + "license": "MIT" }, "node_modules/class-validator": { "version": "0.14.0", - "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz", - "integrity": "sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==", + "license": "MIT", "dependencies": { "@types/validator": "^13.7.10", "libphonenumber-js": "^1.10.14", @@ -3974,8 +3668,7 @@ }, "node_modules/cli-boxes": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "license": "MIT", "engines": { "node": ">=6" }, @@ -3985,9 +3678,8 @@ }, "node_modules/cli-cursor": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, + "license": "MIT", "dependencies": { "restore-cursor": "^3.1.0" }, @@ -3997,9 +3689,8 @@ }, "node_modules/cli-spinners": { "version": "2.9.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz", - "integrity": "sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -4009,9 +3700,8 @@ }, "node_modules/cli-table3": { "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", "dev": true, + "license": "MIT", "dependencies": { "string-width": "^4.2.0" }, @@ -4024,17 +3714,15 @@ }, "node_modules/cli-width": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "dev": true, + "license": "ISC", "engines": { "node": ">= 10" } }, "node_modules/cliui": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -4046,26 +3734,23 @@ }, "node_modules/clone": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8" } }, "node_modules/cluster-key-slot": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "license": "Apache-2.0", "engines": { "node": ">=0.10.0" } }, "node_modules/co": { "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, + "license": "MIT", "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" @@ -4073,14 +3758,12 @@ }, "node_modules/collect-v8-coverage": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -4090,13 +3773,11 @@ }, "node_modules/color-name": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -4106,31 +3787,27 @@ }, "node_modules/commander": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/component-emitter": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "license": "MIT" }, "node_modules/concat-stream": { "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "engines": [ "node >= 0.8" ], + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", @@ -4140,13 +3817,11 @@ }, "node_modules/concat-stream/node_modules/isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "license": "MIT" }, "node_modules/concat-stream/node_modules/readable-stream": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -4159,21 +3834,18 @@ }, "node_modules/concat-stream/node_modules/string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } }, "node_modules/consola": { "version": "2.15.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" + "license": "MIT" }, "node_modules/content-disposition": { "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -4183,8 +3855,6 @@ }, "node_modules/content-disposition/node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -4198,50 +3868,44 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/content-type": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/convert-source-map": { "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cookie": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie-signature": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "license": "MIT" }, "node_modules/cookiejar": { "version": "2.1.4", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", - "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/core-util-is": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "license": "MIT" }, "node_modules/cors": { "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", "dependencies": { "object-assign": "^4", "vary": "^1" @@ -4252,9 +3916,8 @@ }, "node_modules/cosmiconfig": { "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, + "license": "MIT", "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -4268,14 +3931,12 @@ }, "node_modules/create-require": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -4287,8 +3948,7 @@ }, "node_modules/debug": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -4303,29 +3963,25 @@ }, "node_modules/dedent": { "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/deep-is": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + "license": "MIT" }, "node_modules/deepmerge": { "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/defaults": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dev": true, + "license": "MIT", "dependencies": { "clone": "^1.0.2" }, @@ -4335,32 +3991,28 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/denque": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", "engines": { "node": ">=0.10" } }, "node_modules/depd": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/destroy": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -4368,18 +4020,16 @@ }, "node_modules/detect-newline": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/dezalgo": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", - "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", "dev": true, + "license": "ISC", "dependencies": { "asap": "^2.0.0", "wrappy": "1" @@ -4387,26 +4037,23 @@ }, "node_modules/diff": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/diff-sequences": { "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/dir-glob": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -4416,8 +4063,7 @@ }, "node_modules/doctrine": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -4427,16 +4073,14 @@ }, "node_modules/dotenv": { "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" } }, "node_modules/dotenv-cli": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/dotenv-cli/-/dotenv-cli-6.0.0.tgz", - "integrity": "sha512-qXlCOi3UMDhCWFKe0yq5sg3X+pJAz+RQDiFN38AMSbUrnY3uZshSfDJUAge951OS7J9gwLZGfsBlWRSOYz/TRg==", + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "dotenv": "^16.0.0", @@ -4449,36 +4093,31 @@ }, "node_modules/dotenv-cli/node_modules/dotenv-expand": { "version": "8.0.3", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-8.0.3.tgz", - "integrity": "sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" } }, "node_modules/dotenv-expand": { "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", - "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" } }, "node_modules/ee-first": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "license": "MIT" }, "node_modules/electron-to-chromium": { "version": "1.4.417", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.417.tgz", - "integrity": "sha512-8rY8HdCxuSVY8wku3i/eDac4g1b4cSbruzocenrqBlzqruAZYHjQCHIjC66dLR9DXhEHTojsC4EjhZ8KmzwXqA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/emittery": { "version": "0.10.2", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", - "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -4488,31 +4127,27 @@ }, "node_modules/emoji-regex": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "license": "MIT" }, "node_modules/encodeurl": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/end-of-stream": { "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, + "license": "MIT", "dependencies": { "once": "^1.4.0" } }, "node_modules/enhanced-resolve": { "version": "5.14.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz", - "integrity": "sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -4523,36 +4158,31 @@ }, "node_modules/error-ex": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, + "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } }, "node_modules/es-module-lexer": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz", - "integrity": "sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/escalade": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/escape-html": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "license": "MIT" }, "node_modules/escape-string-regexp": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -4562,8 +4192,7 @@ }, "node_modules/eslint": { "version": "8.41.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", - "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", @@ -4617,9 +4246,8 @@ }, "node_modules/eslint-config-prettier": { "version": "8.8.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", - "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", "dev": true, + "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -4629,9 +4257,8 @@ }, "node_modules/eslint-plugin-prettier": { "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", - "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", "dev": true, + "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0" }, @@ -4650,8 +4277,7 @@ }, "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==", + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -4662,8 +4288,7 @@ }, "node_modules/eslint-visitor-keys": { "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -4673,8 +4298,7 @@ }, "node_modules/eslint/node_modules/ajv": { "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -4688,8 +4312,7 @@ }, "node_modules/eslint/node_modules/eslint-scope": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -4703,16 +4326,14 @@ }, "node_modules/eslint/node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -4722,13 +4343,11 @@ }, "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "license": "MIT" }, "node_modules/espree": { "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", @@ -4743,9 +4362,8 @@ }, "node_modules/esprima": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, + "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -4756,8 +4374,7 @@ }, "node_modules/esquery": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -4767,16 +4384,14 @@ }, "node_modules/esquery/node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/esrecurse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -4786,55 +4401,48 @@ }, "node_modules/esrecurse/node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/estraverse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/esutils": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/etag": { "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/eventemitter2": { "version": "6.4.9", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", - "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" + "license": "MIT" }, "node_modules/events": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.x" } }, "node_modules/execa": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -4855,8 +4463,6 @@ }, "node_modules/exit": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true, "engines": { "node": ">= 0.8.0" @@ -4864,9 +4470,8 @@ }, "node_modules/expect": { "version": "29.5.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/expect-utils": "^29.5.0", "jest-get-type": "^29.4.3", @@ -4880,8 +4485,7 @@ }, "node_modules/express": { "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -4921,8 +4525,7 @@ }, "node_modules/express/node_modules/body-parser": { "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.4", @@ -4944,26 +4547,22 @@ }, "node_modules/express/node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, "node_modules/express/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "license": "MIT" }, "node_modules/express/node_modules/path-to-regexp": { "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "license": "MIT" }, "node_modules/express/node_modules/raw-body": { "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -4976,8 +4575,6 @@ }, "node_modules/express/node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -4991,13 +4588,13 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/external-editor": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, + "license": "MIT", "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", @@ -5009,19 +4606,16 @@ }, "node_modules/fast-deep-equal": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "license": "MIT" }, "node_modules/fast-diff": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/fast-glob": { "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -5035,41 +4629,35 @@ }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + "license": "MIT" }, "node_modules/fast-safe-stringify": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" + "license": "MIT" }, "node_modules/fastq": { "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } }, "node_modules/fb-watchman": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "bser": "2.1.1" } }, "node_modules/figures": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.5" }, @@ -5082,17 +4670,15 @@ }, "node_modules/figures/node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/file-entry-cache": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "license": "MIT", "dependencies": { "flat-cache": "^3.0.4" }, @@ -5102,8 +4688,7 @@ }, "node_modules/fill-range": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -5113,8 +4698,7 @@ }, "node_modules/finalhandler": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -5130,21 +4714,18 @@ }, "node_modules/finalhandler/node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "license": "MIT" }, "node_modules/find-up": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -5158,8 +4739,7 @@ }, "node_modules/flat-cache": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "license": "MIT", "dependencies": { "flatted": "^3.1.0", "rimraf": "^3.0.2" @@ -5170,8 +4750,7 @@ }, "node_modules/flat-cache/node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -5184,19 +4763,17 @@ }, "node_modules/flatted": { "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" + "license": "ISC" }, "node_modules/follow-redirects": { "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -5208,9 +4785,8 @@ }, "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==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.16.7", "chalk": "^4.1.2", @@ -5236,8 +4812,7 @@ }, "node_modules/form-data": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -5249,9 +4824,8 @@ }, "node_modules/formidable": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", - "integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==", "dev": true, + "license": "MIT", "dependencies": { "dezalgo": "^1.0.4", "hexoid": "^1.0.0", @@ -5264,25 +4838,22 @@ }, "node_modules/forwarded": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/fresh": { "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/fs-extra": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -5294,41 +4865,35 @@ }, "node_modules/fs-monkey": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", - "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==", - "dev": true + "dev": true, + "license": "Unlicense" }, "node_modules/fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "license": "ISC" }, "node_modules/function-bind": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "license": "MIT" }, "node_modules/gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/get-caller-file": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-intrinsic": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -5341,18 +4906,16 @@ }, "node_modules/get-package-type": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.0.0" } }, "node_modules/get-stream": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -5362,8 +4925,7 @@ }, "node_modules/glob": { "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5381,8 +4943,7 @@ }, "node_modules/glob-parent": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -5392,14 +4953,12 @@ }, "node_modules/glob-to-regexp": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/globals": { "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -5412,8 +4971,7 @@ }, "node_modules/globby": { "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -5431,24 +4989,20 @@ }, "node_modules/graceful-fs": { "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/grapheme-splitter": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" + "license": "MIT" }, "node_modules/graphemer": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + "license": "MIT" }, "node_modules/has": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.1" }, @@ -5458,16 +5012,14 @@ }, "node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/has-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -5477,8 +5029,7 @@ }, "node_modules/has-symbols": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -5488,23 +5039,20 @@ }, "node_modules/hexoid": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", - "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/html-escaper": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/http-errors": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -5518,17 +5066,15 @@ }, "node_modules/human-signals": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10.17.0" } }, "node_modules/iconv-lite": { "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -5538,8 +5084,6 @@ }, "node_modules/ieee754": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true, "funding": [ { @@ -5554,20 +5098,19 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/ignore": { "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -5581,9 +5124,8 @@ }, "node_modules/import-local": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, + "license": "MIT", "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -5600,16 +5142,14 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", "engines": { "node": ">=0.8.19" } }, "node_modules/inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -5617,14 +5157,12 @@ }, "node_modules/inherits": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "license": "ISC" }, "node_modules/inquirer": { "version": "8.2.5", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz", - "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-escapes": "^4.2.1", "chalk": "^4.1.1", @@ -5648,17 +5186,15 @@ }, "node_modules/interpret": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.10" } }, "node_modules/ioredis": { "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.2.tgz", - "integrity": "sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==", + "license": "MIT", "dependencies": { "@ioredis/commands": "^1.1.1", "cluster-key-slot": "^1.1.0", @@ -5680,23 +5216,20 @@ }, "node_modules/ipaddr.js": { "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", "engines": { "node": ">= 0.10" } }, "node_modules/is-arrayish": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-binary-path": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -5706,9 +5239,8 @@ }, "node_modules/is-core-module": { "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", "dev": true, + "license": "MIT", "dependencies": { "has": "^1.0.3" }, @@ -5718,33 +5250,29 @@ }, "node_modules/is-extglob": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-generator-fn": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/is-glob": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -5754,34 +5282,30 @@ }, "node_modules/is-interactive": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-number": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/is-path-inside": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-stream": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -5791,9 +5315,8 @@ }, "node_modules/is-unicode-supported": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -5803,28 +5326,24 @@ }, "node_modules/isarray": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "license": "ISC" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-instrument": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", @@ -5838,18 +5357,16 @@ }, "node_modules/istanbul-lib-instrument/node_modules/semver": { "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/istanbul-lib-report": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", @@ -5861,9 +5378,8 @@ }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -5875,18 +5391,16 @@ }, "node_modules/istanbul-lib-source-maps/node_modules/source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/istanbul-reports": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -5897,17 +5411,15 @@ }, "node_modules/iterare": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", - "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==", + "license": "ISC", "engines": { "node": ">=6" } }, "node_modules/jest": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest/-/jest-28.1.3.tgz", - "integrity": "sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/core": "^28.1.3", "@jest/types": "^28.1.3", @@ -5931,9 +5443,8 @@ }, "node_modules/jest-changed-files": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-28.1.3.tgz", - "integrity": "sha512-esaOfUWJXk2nfZt9SPyC8gA1kNfdKLkQWyzsMlqq8msYSlNKfmZxfRgZn4Cd4MGVUF+7v6dBs0d5TOAKa7iIiA==", "dev": true, + "license": "MIT", "dependencies": { "execa": "^5.0.0", "p-limit": "^3.1.0" @@ -5944,9 +5455,8 @@ }, "node_modules/jest-circus": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.1.3.tgz", - "integrity": "sha512-cZ+eS5zc79MBwt+IhQhiEp0OeBddpc1n8MBo1nMB8A7oPMKEO+Sre+wHaLJexQUj9Ya/8NOBY0RESUgYjB6fow==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^28.1.3", "@jest/expect": "^28.1.3", @@ -5974,9 +5484,8 @@ }, "node_modules/jest-circus/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -5986,18 +5495,16 @@ }, "node_modules/jest-circus/node_modules/diff-sequences": { "version": "28.1.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", - "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", "dev": true, + "license": "MIT", "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, "node_modules/jest-circus/node_modules/jest-diff": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", - "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^28.1.1", @@ -6010,18 +5517,16 @@ }, "node_modules/jest-circus/node_modules/jest-get-type": { "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, "node_modules/jest-circus/node_modules/jest-matcher-utils": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", - "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "jest-diff": "^28.1.3", @@ -6034,9 +5539,8 @@ }, "node_modules/jest-circus/node_modules/jest-message-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", - "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^28.1.3", @@ -6054,9 +5558,8 @@ }, "node_modules/jest-circus/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -6071,9 +5574,8 @@ }, "node_modules/jest-circus/node_modules/pretty-format": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", @@ -6086,9 +5588,8 @@ }, "node_modules/jest-cli": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.1.3.tgz", - "integrity": "sha512-roY3kvrv57Azn1yPgdTebPAXvdR2xfezaKKYzVxZ6It/5NCxzJym6tUI5P1zkdWhfUYkxEI9uZWcQdaFLo8mJQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/core": "^28.1.3", "@jest/test-result": "^28.1.3", @@ -6120,9 +5621,8 @@ }, "node_modules/jest-cli/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -6137,9 +5637,8 @@ }, "node_modules/jest-config": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.1.3.tgz", - "integrity": "sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^28.1.3", @@ -6182,9 +5681,8 @@ }, "node_modules/jest-config/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -6194,18 +5692,16 @@ }, "node_modules/jest-config/node_modules/jest-get-type": { "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, "node_modules/jest-config/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -6220,9 +5716,8 @@ }, "node_modules/jest-config/node_modules/pretty-format": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", @@ -6235,9 +5730,8 @@ }, "node_modules/jest-diff": { "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.4.3", @@ -6250,9 +5744,8 @@ }, "node_modules/jest-docblock": { "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-28.1.1.tgz", - "integrity": "sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA==", "dev": true, + "license": "MIT", "dependencies": { "detect-newline": "^3.0.0" }, @@ -6262,9 +5755,8 @@ }, "node_modules/jest-each": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-28.1.3.tgz", - "integrity": "sha512-arT1z4sg2yABU5uogObVPvSlSMQlDA48owx07BDPAiasW0yYpYHYOo4HHLz9q0BVzDVU4hILFjzJw0So9aCL/g==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "chalk": "^4.0.0", @@ -6278,9 +5770,8 @@ }, "node_modules/jest-each/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -6290,18 +5781,16 @@ }, "node_modules/jest-each/node_modules/jest-get-type": { "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, "node_modules/jest-each/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -6316,9 +5805,8 @@ }, "node_modules/jest-each/node_modules/pretty-format": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", @@ -6331,9 +5819,8 @@ }, "node_modules/jest-environment-node": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.1.3.tgz", - "integrity": "sha512-ugP6XOhEpjAEhGYvp5Xj989ns5cB1K6ZdjBYuS30umT4CQEETaxSiPcZ/E1kFktX4GkrcM4qu07IIlDYX1gp+A==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^28.1.3", "@jest/fake-timers": "^28.1.3", @@ -6348,9 +5835,8 @@ }, "node_modules/jest-environment-node/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -6365,18 +5851,16 @@ }, "node_modules/jest-get-type": { "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-haste-map": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.1.3.tgz", - "integrity": "sha512-3S+RQWDXccXDKSWnkHa/dPwt+2qwA8CJzR61w3FoYCvoo3Pn8tvGcysmMF0Bj0EX5RYvAI2EIvC57OmotfdtKA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/graceful-fs": "^4.1.3", @@ -6399,9 +5883,8 @@ }, "node_modules/jest-haste-map/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -6416,9 +5899,8 @@ }, "node_modules/jest-leak-detector": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-28.1.3.tgz", - "integrity": "sha512-WFVJhnQsiKtDEo5lG2mM0v40QWnBM+zMdHHyJs8AWZ7J0QZJS59MsyKeJHWhpBZBH32S48FOVvGyOFT1h0DlqA==", "dev": true, + "license": "MIT", "dependencies": { "jest-get-type": "^28.0.2", "pretty-format": "^28.1.3" @@ -6429,9 +5911,8 @@ }, "node_modules/jest-leak-detector/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -6441,18 +5922,16 @@ }, "node_modules/jest-leak-detector/node_modules/jest-get-type": { "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, "node_modules/jest-leak-detector/node_modules/pretty-format": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", @@ -6465,9 +5944,8 @@ }, "node_modules/jest-matcher-utils": { "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", - "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "jest-diff": "^29.5.0", @@ -6480,9 +5958,8 @@ }, "node_modules/jest-message-util": { "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", - "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^29.5.0", @@ -6500,9 +5977,8 @@ }, "node_modules/jest-message-util/node_modules/@jest/schemas": { "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", "dev": true, + "license": "MIT", "dependencies": { "@sinclair/typebox": "^0.25.16" }, @@ -6512,9 +5988,8 @@ }, "node_modules/jest-message-util/node_modules/@jest/types": { "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.4.3", "@types/istanbul-lib-coverage": "^2.0.0", @@ -6529,15 +6004,13 @@ }, "node_modules/jest-message-util/node_modules/@sinclair/typebox": { "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jest-mock": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-28.1.3.tgz", - "integrity": "sha512-o3J2jr6dMMWYVH4Lh/NKmDXdosrsJgi4AviS8oXLujcjpCMBb1FMsblDnOXKZKfSiHLxYub1eS0IHuRXsio9eA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*" @@ -6548,9 +6021,8 @@ }, "node_modules/jest-pnp-resolver": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -6565,18 +6037,16 @@ }, "node_modules/jest-regex-util": { "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", "dev": true, + "license": "MIT", "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, "node_modules/jest-resolve": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.1.3.tgz", - "integrity": "sha512-Z1W3tTjE6QaNI90qo/BJpfnvpxtaFTFw5CDgwpyE/Kz8U/06N1Hjf4ia9quUhCh39qIGWF1ZuxFiBiJQwSEYKQ==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", @@ -6594,9 +6064,8 @@ }, "node_modules/jest-resolve-dependencies": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.3.tgz", - "integrity": "sha512-qa0QO2Q0XzQoNPouMbCc7Bvtsem8eQgVPNkwn9LnS+R2n8DaVDPL/U1gngC0LTl1RYXJU0uJa2BMC2DbTfFrHA==", "dev": true, + "license": "MIT", "dependencies": { "jest-regex-util": "^28.0.2", "jest-snapshot": "^28.1.3" @@ -6607,9 +6076,8 @@ }, "node_modules/jest-resolve/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -6624,9 +6092,8 @@ }, "node_modules/jest-runner": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.1.3.tgz", - "integrity": "sha512-GkMw4D/0USd62OVO0oEgjn23TM+YJa2U2Wu5zz9xsQB1MxWKDOlrnykPxnMsN0tnJllfLPinHTka61u0QhaxBA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^28.1.3", "@jest/environment": "^28.1.3", @@ -6656,9 +6123,8 @@ }, "node_modules/jest-runner/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -6668,9 +6134,8 @@ }, "node_modules/jest-runner/node_modules/jest-message-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", - "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^28.1.3", @@ -6688,9 +6153,8 @@ }, "node_modules/jest-runner/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -6705,9 +6169,8 @@ }, "node_modules/jest-runner/node_modules/pretty-format": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", @@ -6720,18 +6183,16 @@ }, "node_modules/jest-runner/node_modules/source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/jest-runner/node_modules/source-map-support": { "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -6739,9 +6200,8 @@ }, "node_modules/jest-runtime": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.1.3.tgz", - "integrity": "sha512-NU+881ScBQQLc1JHG5eJGU7Ui3kLKrmwCPPtYsJtBykixrM2OhVQlpMmFWJjMyDfdkGgBMNjXCGB/ebzsgNGQw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^28.1.3", "@jest/fake-timers": "^28.1.3", @@ -6772,9 +6232,8 @@ }, "node_modules/jest-runtime/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -6784,9 +6243,8 @@ }, "node_modules/jest-runtime/node_modules/jest-message-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", - "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^28.1.3", @@ -6804,9 +6262,8 @@ }, "node_modules/jest-runtime/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -6821,9 +6278,8 @@ }, "node_modules/jest-runtime/node_modules/pretty-format": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", @@ -6836,9 +6292,8 @@ }, "node_modules/jest-snapshot": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.1.3.tgz", - "integrity": "sha512-4lzMgtiNlc3DU/8lZfmqxN3AYD6GGLbl+72rdBpXvcV+whX7mDrREzkPdp2RnmfIiWBg1YbuFSkXduF2JcafJg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", @@ -6870,9 +6325,8 @@ }, "node_modules/jest-snapshot/node_modules/@jest/expect-utils": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-28.1.3.tgz", - "integrity": "sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA==", "dev": true, + "license": "MIT", "dependencies": { "jest-get-type": "^28.0.2" }, @@ -6882,9 +6336,8 @@ }, "node_modules/jest-snapshot/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -6894,18 +6347,16 @@ }, "node_modules/jest-snapshot/node_modules/diff-sequences": { "version": "28.1.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", - "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", "dev": true, + "license": "MIT", "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, "node_modules/jest-snapshot/node_modules/expect": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/expect/-/expect-28.1.3.tgz", - "integrity": "sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g==", "dev": true, + "license": "MIT", "dependencies": { "@jest/expect-utils": "^28.1.3", "jest-get-type": "^28.0.2", @@ -6919,9 +6370,8 @@ }, "node_modules/jest-snapshot/node_modules/jest-diff": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", - "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^28.1.1", @@ -6934,18 +6384,16 @@ }, "node_modules/jest-snapshot/node_modules/jest-get-type": { "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, "node_modules/jest-snapshot/node_modules/jest-matcher-utils": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", - "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "jest-diff": "^28.1.3", @@ -6958,9 +6406,8 @@ }, "node_modules/jest-snapshot/node_modules/jest-message-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", - "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^28.1.3", @@ -6978,9 +6425,8 @@ }, "node_modules/jest-snapshot/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -6995,9 +6441,8 @@ }, "node_modules/jest-snapshot/node_modules/pretty-format": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", @@ -7010,9 +6455,8 @@ }, "node_modules/jest-util": { "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.5.0", "@types/node": "*", @@ -7027,9 +6471,8 @@ }, "node_modules/jest-util/node_modules/@jest/schemas": { "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", "dev": true, + "license": "MIT", "dependencies": { "@sinclair/typebox": "^0.25.16" }, @@ -7039,9 +6482,8 @@ }, "node_modules/jest-util/node_modules/@jest/types": { "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.4.3", "@types/istanbul-lib-coverage": "^2.0.0", @@ -7056,15 +6498,13 @@ }, "node_modules/jest-util/node_modules/@sinclair/typebox": { "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jest-validate": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.1.3.tgz", - "integrity": "sha512-SZbOGBWEsaTxBGCOpsRWlXlvNkvTkY0XxRfh7zYmvd8uL5Qzyg0CHAXiXKROflh801quA6+/DsT4ODDthOC/OA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "camelcase": "^6.2.0", @@ -7079,9 +6519,8 @@ }, "node_modules/jest-validate/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -7091,18 +6530,16 @@ }, "node_modules/jest-validate/node_modules/jest-get-type": { "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, "node_modules/jest-validate/node_modules/pretty-format": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", @@ -7115,9 +6552,8 @@ }, "node_modules/jest-watcher": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", - "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", "dev": true, + "license": "MIT", "dependencies": { "@jest/test-result": "^28.1.3", "@jest/types": "^28.1.3", @@ -7134,9 +6570,8 @@ }, "node_modules/jest-watcher/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -7151,9 +6586,8 @@ }, "node_modules/jest-worker": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", - "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -7165,9 +6599,8 @@ }, "node_modules/jest-worker/node_modules/supports-color": { "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -7180,14 +6613,12 @@ }, "node_modules/js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -7197,9 +6628,8 @@ }, "node_modules/jsesc": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -7209,26 +6639,22 @@ }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + "license": "MIT" }, "node_modules/json5": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -7238,15 +6664,13 @@ }, "node_modules/jsonc-parser": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jsonfile": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -7256,26 +6680,23 @@ }, "node_modules/kleur": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/leven": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/levn": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -7286,28 +6707,24 @@ }, "node_modules/libphonenumber-js": { "version": "1.10.31", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.31.tgz", - "integrity": "sha512-qYTzElLePmz3X/6I0JPX5n87tu7jVIMtR/yRLi5PGVPvMCMSVTCR+079KmdNK005i4dBjFxY/bMYceI9IBp47w==" + "license": "MIT" }, "node_modules/lines-and-columns": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/loader-runner": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.11.5" } }, "node_modules/locate-path": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -7320,45 +6737,37 @@ }, "node_modules/lodash": { "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "license": "MIT" }, "node_modules/lodash.camelcase": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + "license": "MIT" }, "node_modules/lodash.clonedeep": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + "license": "MIT" }, "node_modules/lodash.defaults": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" + "license": "MIT" }, "node_modules/lodash.isarguments": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" + "license": "MIT" }, "node_modules/lodash.memoize": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "license": "MIT" }, "node_modules/log-symbols": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -7372,22 +6781,19 @@ }, "node_modules/long": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + "license": "Apache-2.0" }, "node_modules/lru-cache": { "version": "9.1.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.2.tgz", - "integrity": "sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==", + "license": "ISC", "engines": { "node": "14 || >=16.14" } }, "node_modules/macos-release": { "version": "2.5.1", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.1.tgz", - "integrity": "sha512-DXqXhEM7gW59OjZO8NIjBCz9AQ1BEMrfiOAl4AYByHCtVHRF4KoGNO8mqQeM8lRCtQe/UnJ4imO/d2HdkKsd+A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -7397,9 +6803,8 @@ }, "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, + "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.13" }, @@ -7409,9 +6814,8 @@ }, "node_modules/make-dir": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^6.0.0" }, @@ -7424,41 +6828,36 @@ }, "node_modules/make-dir/node_modules/semver": { "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/make-error": { "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/makeerror": { "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "tmpl": "1.0.5" } }, "node_modules/media-typer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/memfs": { "version": "3.5.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.1.tgz", - "integrity": "sha512-UWbFJKvj5k+nETdteFndTpYxdeTMox/ULeqX5k/dpaQJCCFmj5EeKv3dBcyO2xmkRAx2vppRu5dVG7SOtsGOzA==", "dev": true, + "license": "Unlicense", "dependencies": { "fs-monkey": "^1.0.3" }, @@ -7468,35 +6867,30 @@ }, "node_modules/merge-descriptors": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "license": "MIT" }, "node_modules/merge-stream": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/merge2": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/methods": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/micromatch": { "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "license": "MIT", "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -7507,8 +6901,7 @@ }, "node_modules/mime": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -7518,16 +6911,14 @@ }, "node_modules/mime-db": { "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -7537,17 +6928,15 @@ }, "node_modules/mimic-fn": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/minimatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -7557,25 +6946,22 @@ }, "node_modules/minimist": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/minipass": { "version": "4.2.8", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=8" } }, "node_modules/mkdirp": { "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", "dependencies": { "minimist": "^1.2.6" }, @@ -7585,13 +6971,11 @@ }, "node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "license": "MIT" }, "node_modules/multer": { "version": "1.4.4-lts.1", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz", - "integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==", + "license": "MIT", "dependencies": { "append-field": "^1.0.0", "busboy": "^1.0.0", @@ -7607,20 +6991,18 @@ }, "node_modules/mute-stream": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/nanoid": { "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -7630,47 +7012,40 @@ }, "node_modules/natural-compare": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + "license": "MIT" }, "node_modules/natural-compare-lite": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==" + "license": "MIT" }, "node_modules/negotiator": { "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/neo-async": { "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-abort-controller": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-emoji": { "version": "1.11.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", - "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", "dev": true, + "license": "MIT", "dependencies": { "lodash": "^4.17.21" } }, "node_modules/node-fetch": { "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -7688,30 +7063,26 @@ }, "node_modules/node-int64": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-releases": { "version": "2.0.12", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", - "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/normalize-path": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/npm-run-path": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.0.0" }, @@ -7721,24 +7092,21 @@ }, "node_modules/object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/on-finished": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -7748,17 +7116,15 @@ }, "node_modules/once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", "dependencies": { "wrappy": "1" } }, "node_modules/onetime": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" }, @@ -7771,8 +7137,7 @@ }, "node_modules/optionator": { "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -7787,9 +7152,8 @@ }, "node_modules/ora": { "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dev": true, + "license": "MIT", "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", @@ -7810,9 +7174,8 @@ }, "node_modules/os-name": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-4.0.1.tgz", - "integrity": "sha512-xl9MAoU97MH1Xt5K9ERft2YfCAoaO6msy1OBA0ozxEC0x0TmIoE6K3QvgJMMZA9yKGLmHXNY/YZoDbiGDj4zYw==", "dev": true, + "license": "MIT", "dependencies": { "macos-release": "^2.5.0", "windows-release": "^4.0.0" @@ -7826,17 +7189,15 @@ }, "node_modules/os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/p-limit": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -7849,8 +7210,7 @@ }, "node_modules/p-locate": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -7863,17 +7223,15 @@ }, "node_modules/p-try": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/parent-module": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -7883,9 +7241,8 @@ }, "node_modules/parse-json": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -7901,47 +7258,41 @@ }, "node_modules/parseurl": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/path-key": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-parse": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-scurry": { "version": "1.9.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.9.2.tgz", - "integrity": "sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^9.1.1", "minipass": "^5.0.0 || ^6.0.2" @@ -7955,36 +7306,31 @@ }, "node_modules/path-scurry/node_modules/minipass": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-6.0.2.tgz", - "integrity": "sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==", "dev": true, + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/path-to-regexp": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", - "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==" + "license": "MIT" }, "node_modules/path-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/picocolors": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -7994,18 +7340,16 @@ }, "node_modules/pirates": { "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/pkg-dir": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, @@ -8015,9 +7359,8 @@ }, "node_modules/pkg-dir/node_modules/find-up": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -8028,9 +7371,8 @@ }, "node_modules/pkg-dir/node_modules/locate-path": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -8040,9 +7382,8 @@ }, "node_modules/pkg-dir/node_modules/p-limit": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -8055,9 +7396,8 @@ }, "node_modules/pkg-dir/node_modules/p-locate": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -8067,26 +7407,23 @@ }, "node_modules/pluralize": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/prelude-ls": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "license": "MIT", "engines": { "node": ">= 0.8.0" } }, "node_modules/prettier": { "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin-prettier.js" }, @@ -8099,9 +7436,8 @@ }, "node_modules/prettier-linter-helpers": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, + "license": "MIT", "dependencies": { "fast-diff": "^1.1.2" }, @@ -8111,9 +7447,8 @@ }, "node_modules/pretty-format": { "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.4.3", "ansi-styles": "^5.0.0", @@ -8125,9 +7460,8 @@ }, "node_modules/pretty-format/node_modules/@jest/schemas": { "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", "dev": true, + "license": "MIT", "dependencies": { "@sinclair/typebox": "^0.25.16" }, @@ -8137,15 +7471,13 @@ }, "node_modules/pretty-format/node_modules/@sinclair/typebox": { "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -8155,10 +7487,9 @@ }, "node_modules/prisma": { "version": "4.15.0", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.15.0.tgz", - "integrity": "sha512-iKZZpobPl48gTcSZVawLMQ3lEy6BnXwtoMj7hluoGFYu2kQ6F9LBuBrUyF95zRVnNo8/3KzLXJXJ5TEnLSJFiA==", "devOptional": true, "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { "@prisma/engines": "4.15.0" }, @@ -8172,19 +7503,16 @@ }, "node_modules/process-nextick-args": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "license": "MIT" }, "node_modules/promise-breaker": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/promise-breaker/-/promise-breaker-5.0.0.tgz", - "integrity": "sha512-mgsWQuG4kJ1dtO6e/QlNDLFtMkMzzecsC69aI5hlLEjGHFNpHrvGhFi4LiK5jg2SMQj74/diH+wZliL9LpGsyA==" + "license": "MIT" }, "node_modules/prompts": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, + "license": "MIT", "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" @@ -8195,9 +7523,8 @@ }, "node_modules/protobufjs": { "version": "7.2.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz", - "integrity": "sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ==", "hasInstallScript": true, + "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -8218,13 +7545,11 @@ }, "node_modules/protobufjs/node_modules/long": { "version": "5.2.3", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + "license": "Apache-2.0" }, "node_modules/proxy-addr": { "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -8235,14 +7560,12 @@ }, "node_modules/proxy-from-env": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + "license": "MIT" }, "node_modules/pump": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -8250,16 +7573,14 @@ }, "node_modules/punycode": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/qs": { "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.4" }, @@ -8272,13 +7593,10 @@ }, "node_modules/querystringify": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + "license": "MIT" }, "node_modules/queue-microtask": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "funding": [ { "type": "github", @@ -8292,29 +7610,27 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/randombytes": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } }, "node_modules/range-parser": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/raw-body": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -8327,14 +7643,12 @@ }, "node_modules/react-is": { "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", @@ -8344,9 +7658,8 @@ }, "node_modules/readdirp": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -8356,8 +7669,6 @@ }, "node_modules/rechoir": { "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", "dev": true, "dependencies": { "resolve": "^1.1.6" @@ -8368,16 +7679,14 @@ }, "node_modules/redis-errors": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/redis-parser": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "license": "MIT", "dependencies": { "redis-errors": "^1.0.0" }, @@ -8387,37 +7696,32 @@ }, "node_modules/reflect-metadata": { "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "license": "Apache-2.0", "peer": true }, "node_modules/require-directory": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/require-from-string": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/requires-port": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + "license": "MIT" }, "node_modules/resolve": { "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.11.0", "path-parse": "^1.0.7", @@ -8432,9 +7736,8 @@ }, "node_modules/resolve-cwd": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, + "license": "MIT", "dependencies": { "resolve-from": "^5.0.0" }, @@ -8444,35 +7747,31 @@ }, "node_modules/resolve-cwd/node_modules/resolve-from": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/resolve-from": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/resolve.exports": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", - "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/restore-cursor": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, + "license": "MIT", "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -8483,8 +7782,7 @@ }, "node_modules/reusify": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -8492,9 +7790,8 @@ }, "node_modules/rimraf": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", - "integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^9.2.0" }, @@ -8510,18 +7807,16 @@ }, "node_modules/rimraf/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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/rimraf/node_modules/glob": { "version": "9.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", - "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "minimatch": "^8.0.2", @@ -8537,9 +7832,8 @@ }, "node_modules/rimraf/node_modules/minimatch": { "version": "8.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", - "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -8552,17 +7846,14 @@ }, "node_modules/run-async": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/run-parallel": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "funding": [ { "type": "github", @@ -8577,33 +7868,30 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } }, "node_modules/rxjs": { "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" } }, "node_modules/safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "license": "MIT" }, "node_modules/schema-utils": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -8619,9 +7907,8 @@ }, "node_modules/schema-utils/node_modules/ajv": { "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -8635,23 +7922,20 @@ }, "node_modules/schema-utils/node_modules/ajv-keywords": { "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, + "license": "MIT", "peerDependencies": { "ajv": "^6.9.1" } }, "node_modules/schema-utils/node_modules/json-schema-traverse": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/semver": { "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -8664,8 +7948,7 @@ }, "node_modules/semver/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -8675,13 +7958,11 @@ }, "node_modules/semver/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, "node_modules/send": { "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -8703,35 +7984,30 @@ }, "node_modules/send/node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "license": "MIT" }, "node_modules/send/node_modules/ms": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "license": "MIT" }, "node_modules/serialize-javascript": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/serve-static": { "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "license": "MIT", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", @@ -8744,13 +8020,11 @@ }, "node_modules/setprototypeof": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "license": "ISC" }, "node_modules/shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -8760,17 +8034,15 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/shelljs": { "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", @@ -8785,8 +8057,7 @@ }, "node_modules/side-channel": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -8798,38 +8069,33 @@ }, "node_modules/signal-exit": { "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/sisteransi": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/slash": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/source-map": { "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">= 8" } }, "node_modules/source-map-support": { "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -8837,24 +8103,21 @@ }, "node_modules/source-map-support/node_modules/source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/sprintf-js": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/stack-utils": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^2.0.0" }, @@ -8864,44 +8127,37 @@ }, "node_modules/stack-utils/node_modules/escape-string-regexp": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/standard-as-callback": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", - "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" + "license": "MIT" }, "node_modules/statuses": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/streamsearch": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", "engines": { "node": ">=10.0.0" } }, "node_modules/string_decoder": { "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + "license": "MIT" }, "node_modules/string-length": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, + "license": "MIT", "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" @@ -8912,8 +8168,7 @@ }, "node_modules/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==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -8925,8 +8180,7 @@ }, "node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -8936,26 +8190,23 @@ }, "node_modules/strip-bom": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/strip-final-newline": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/strip-json-comments": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", "engines": { "node": ">=8" }, @@ -8965,9 +8216,8 @@ }, "node_modules/superagent": { "version": "8.0.9", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.0.9.tgz", - "integrity": "sha512-4C7Bh5pyHTvU33KpZgwrNKh/VQnvgtCSqPRfJAUdmrtSYePVzVg4E4OzsrbkhJj9O7SO6Bnv75K/F8XVZT8YHA==", "dev": true, + "license": "MIT", "dependencies": { "component-emitter": "^1.3.0", "cookiejar": "^2.1.4", @@ -8986,9 +8236,8 @@ }, "node_modules/superagent/node_modules/mime": { "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true, + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -8998,9 +8247,8 @@ }, "node_modules/supertest": { "version": "6.3.3", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.3.tgz", - "integrity": "sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA==", "dev": true, + "license": "MIT", "dependencies": { "methods": "^1.1.2", "superagent": "^8.0.5" @@ -9011,8 +8259,7 @@ }, "node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -9022,9 +8269,8 @@ }, "node_modules/supports-hyperlinks": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" @@ -9035,9 +8281,8 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -9047,27 +8292,24 @@ }, "node_modules/symbol-observable": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10" } }, "node_modules/tapable": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/terminal-link": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-escapes": "^4.2.1", "supports-hyperlinks": "^2.0.0" @@ -9081,9 +8323,8 @@ }, "node_modules/terser": { "version": "5.17.7", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.7.tgz", - "integrity": "sha512-/bi0Zm2C6VAexlGgLlVxA0P2lru/sdLyfCVaRMfKVo9nWxbmz7f/sD8VPybPeSUJaJcwmCJis9pBIhcVcG1QcQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -9099,9 +8340,8 @@ }, "node_modules/terser-webpack-plugin": { "version": "5.3.9", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", - "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", @@ -9133,9 +8373,8 @@ }, "node_modules/terser-webpack-plugin/node_modules/jest-worker": { "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -9147,9 +8386,8 @@ }, "node_modules/terser-webpack-plugin/node_modules/supports-color": { "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -9162,15 +8400,13 @@ }, "node_modules/terser/node_modules/commander": { "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/test-exclude": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, + "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -9182,20 +8418,17 @@ }, "node_modules/text-table": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + "license": "MIT" }, "node_modules/through": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/tmp": { "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, + "license": "MIT", "dependencies": { "os-tmpdir": "~1.0.2" }, @@ -9205,23 +8438,20 @@ }, "node_modules/tmpl": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/to-regex-range": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -9231,31 +8461,27 @@ }, "node_modules/toidentifier": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } }, "node_modules/tr46": { "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + "license": "MIT" }, "node_modules/tree-kill": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true, + "license": "MIT", "bin": { "tree-kill": "cli.js" } }, "node_modules/ts-jest": { "version": "28.0.8", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-28.0.8.tgz", - "integrity": "sha512-5FaG0lXmRPzApix8oFG8RKjAz4ehtm8yMKOTy5HX3fY6W8kmvOrmcY0hKDElW52FJov+clhUbrKAqofnj4mXTg==", "dev": true, + "license": "MIT", "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", @@ -9296,9 +8522,8 @@ }, "node_modules/ts-jest/node_modules/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -9313,9 +8538,8 @@ }, "node_modules/ts-loader": { "version": "9.4.3", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.3.tgz", - "integrity": "sha512-n3hBnm6ozJYzwiwt5YRiJZkzktftRpMiBApHaJPoWLA+qetQBAXkHqCLM6nwSdRDimqVtA5ocIkcTRLMTt7yzA==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "enhanced-resolve": "^5.0.0", @@ -9332,9 +8556,8 @@ }, "node_modules/ts-node": { "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, + "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -9375,9 +8598,8 @@ }, "node_modules/tsconfig-paths": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.1.0.tgz", - "integrity": "sha512-AHx4Euop/dXFC+Vx589alFba8QItjF+8hf8LtmuiCwHyI4rHXQtOOENaM8kvYf5fR0dRChy3wzWIZ9WbB7FWow==", "dev": true, + "license": "MIT", "dependencies": { "json5": "^2.2.1", "minimist": "^1.2.6", @@ -9389,9 +8611,8 @@ }, "node_modules/tsconfig-paths-webpack-plugin": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.0.1.tgz", - "integrity": "sha512-m5//KzLoKmqu2MVix+dgLKq70MnFi8YL8sdzQZ6DblmCdfuq/y3OqvJd5vMndg2KEVCOeNz8Es4WVZhYInteLw==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "enhanced-resolve": "^5.7.0", @@ -9403,18 +8624,16 @@ }, "node_modules/tsconfig-paths-webpack-plugin/node_modules/strip-bom": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/tsconfig-paths-webpack-plugin/node_modules/tsconfig-paths": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, + "license": "MIT", "dependencies": { "json5": "^2.2.2", "minimist": "^1.2.6", @@ -9426,22 +8645,19 @@ }, "node_modules/tsconfig-paths/node_modules/strip-bom": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "node_modules/tsutils": { "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "license": "MIT", "dependencies": { "tslib": "^1.8.1" }, @@ -9454,13 +8670,11 @@ }, "node_modules/tsutils/node_modules/tslib": { "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "license": "0BSD" }, "node_modules/type-check": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -9470,17 +8684,15 @@ }, "node_modules/type-detect": { "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/type-fest": { "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -9490,8 +8702,7 @@ }, "node_modules/type-is": { "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -9502,13 +8713,11 @@ }, "node_modules/typedarray": { "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + "license": "MIT" }, "node_modules/typescript": { "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9519,8 +8728,7 @@ }, "node_modules/uid": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", - "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", + "license": "MIT", "dependencies": { "@lukeed/csprng": "^1.0.0" }, @@ -9530,25 +8738,21 @@ }, "node_modules/universalify": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } }, "node_modules/unpipe": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/update-browserslist-db": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", "dev": true, "funding": [ { @@ -9564,6 +8768,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -9577,16 +8782,14 @@ }, "node_modules/uri-js": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, "node_modules/url-parse": { "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "license": "MIT", "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -9594,36 +8797,31 @@ }, "node_modules/util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "license": "MIT" }, "node_modules/utils-merge": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", "engines": { "node": ">= 0.4.0" } }, "node_modules/uuid": { "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/v8-to-istanbul": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", "dev": true, + "license": "ISC", "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", @@ -9635,34 +8833,30 @@ }, "node_modules/validator": { "version": "13.9.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.9.0.tgz", - "integrity": "sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==", + "license": "MIT", "engines": { "node": ">= 0.10" } }, "node_modules/vary": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/walker": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "makeerror": "1.0.12" } }, "node_modules/watchpack": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "dev": true, + "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -9673,23 +8867,20 @@ }, "node_modules/wcwidth": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "dev": true, + "license": "MIT", "dependencies": { "defaults": "^1.0.3" } }, "node_modules/webidl-conversions": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + "license": "BSD-2-Clause" }, "node_modules/webpack": { "version": "5.85.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.85.0.tgz", - "integrity": "sha512-7gazTiYqwo5OSqwH1tigLDL2r3qDeP2dOKYgd+LlXpsUMqDTklg6tOghexqky0/+6QY38kb/R/uRPUleuL43zg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.3", @@ -9735,26 +8926,23 @@ }, "node_modules/webpack-node-externals": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", - "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/webpack-sources": { "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.13.0" } }, "node_modules/whatwg-url": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -9762,8 +8950,7 @@ }, "node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -9776,8 +8963,7 @@ }, "node_modules/widest-line": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "license": "MIT", "dependencies": { "string-width": "^4.0.0" }, @@ -9787,9 +8973,8 @@ }, "node_modules/windows-release": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-4.0.0.tgz", - "integrity": "sha512-OxmV4wzDKB1x7AZaZgXMVsdJ1qER1ed83ZrTYd5Bwq2HfJVg3DJS8nqlAG4sMoJ7mu8cuRmLEYyU13BKwctRAg==", "dev": true, + "license": "MIT", "dependencies": { "execa": "^4.0.2" }, @@ -9802,9 +8987,8 @@ }, "node_modules/windows-release/node_modules/execa": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.0", "get-stream": "^5.0.0", @@ -9825,9 +9009,8 @@ }, "node_modules/windows-release/node_modules/get-stream": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, + "license": "MIT", "dependencies": { "pump": "^3.0.0" }, @@ -9840,25 +9023,22 @@ }, "node_modules/windows-release/node_modules/human-signals": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=8.12.0" } }, "node_modules/word-wrap": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", - "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/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==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -9873,14 +9053,12 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "license": "ISC" }, "node_modules/write-file-atomic": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" @@ -9891,39 +9069,34 @@ }, "node_modules/xtend": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", "engines": { "node": ">=0.4" } }, "node_modules/y18n": { "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yallist": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, "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, + "license": "ISC", "engines": { "node": ">= 6" } }, "node_modules/yargs": { "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -9939,25 +9112,22 @@ }, "node_modules/yargs-parser": { "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", "engines": { "node": ">=12" } }, "node_modules/yn": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/yocto-queue": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index b6893b0..21d1ea2 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@grpc/proto-loader": "^0.7.4", "@liaoliaots/nestjs-redis": "^9.0.5", "@mobicoop/configuration-module": "^1.2.0", - "@mobicoop/ddd-library": "^0.3.0", + "@mobicoop/ddd-library": "file:../../packages/dddlibrary", "@mobicoop/health-module": "^2.0.0", "@mobicoop/message-broker-module": "^1.2.0", "@nestjs/cache-manager": "^1.0.0", @@ -87,6 +87,7 @@ "modulePathIgnorePatterns": [ ".module.ts", ".dto.ts", + ".constants.ts", ".di-tokens.ts", ".response.ts", ".port.ts", @@ -104,6 +105,7 @@ "coveragePathIgnorePatterns": [ ".module.ts", ".dto.ts", + ".constants.ts", ".di-tokens.ts", ".response.ts", ".port.ts", diff --git a/src/modules/user/core/application/event-handlers/publish-message-when-user-is-created.domain-event-handler.ts b/src/modules/user/core/application/event-handlers/publish-message-when-user-is-created.domain-event-handler.ts index 3fcab00..c5acccc 100644 --- a/src/modules/user/core/application/event-handlers/publish-message-when-user-is-created.domain-event-handler.ts +++ b/src/modules/user/core/application/event-handlers/publish-message-when-user-is-created.domain-event-handler.ts @@ -2,7 +2,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; import { MessagePublisherPort } from '@mobicoop/ddd-library'; import { USER_MESSAGE_PUBLISHER } from '@modules/user/user.di-tokens'; -import { UserCreatedDomainEvent } from '../../domain/events/user-created.domain-events'; +import { UserCreatedDomainEvent } from '../../domain/events/user-created.domain-event'; +import { UserCreatedIntegrationEvent } from '../events/user-created.integration-event'; +import { USER_CREATED_ROUTING_KEY } from '@modules/user/user.constants'; @Injectable() export class PublishMessageWhenUserIsCreatedDomainEventHandler { @@ -13,6 +15,17 @@ export class PublishMessageWhenUserIsCreatedDomainEventHandler { @OnEvent(UserCreatedDomainEvent.name, { async: true, promisify: true }) async handle(event: UserCreatedDomainEvent): Promise { - this.messagePublisher.publish('user.created', JSON.stringify(event)); + const userCreatedIntegrationEvent = new UserCreatedIntegrationEvent({ + id: event.aggregateId, + firstName: event.firstName, + lastName: event.lastName, + email: event.email, + phone: event.phone, + metadata: event.metadata, + }); + this.messagePublisher.publish( + USER_CREATED_ROUTING_KEY, + JSON.stringify(userCreatedIntegrationEvent), + ); } } diff --git a/src/modules/user/core/application/event-handlers/publish-message-when-user-is-deleted.domain-event-handler.ts b/src/modules/user/core/application/event-handlers/publish-message-when-user-is-deleted.domain-event-handler.ts index d3c2893..3fe84da 100644 --- a/src/modules/user/core/application/event-handlers/publish-message-when-user-is-deleted.domain-event-handler.ts +++ b/src/modules/user/core/application/event-handlers/publish-message-when-user-is-deleted.domain-event-handler.ts @@ -3,6 +3,8 @@ import { OnEvent } from '@nestjs/event-emitter'; import { MessagePublisherPort } from '@mobicoop/ddd-library'; import { USER_MESSAGE_PUBLISHER } from '@modules/user/user.di-tokens'; import { UserDeletedDomainEvent } from '../../domain/events/user-deleted.domain-event'; +import { UserDeletedIntegrationEvent } from '../events/user-deleted.integration-event'; +import { USER_DELETED_ROUTING_KEY } from '@modules/user/user.constants'; @Injectable() export class PublishMessageWhenUserIsDeletedDomainEventHandler { @@ -13,6 +15,13 @@ export class PublishMessageWhenUserIsDeletedDomainEventHandler { @OnEvent(UserDeletedDomainEvent.name, { async: true, promisify: true }) async handle(event: UserDeletedDomainEvent): Promise { - this.messagePublisher.publish('user.deleted', JSON.stringify(event)); + const userDeletedIntegrationEvent = new UserDeletedIntegrationEvent({ + id: event.aggregateId, + metadata: event.metadata, + }); + this.messagePublisher.publish( + USER_DELETED_ROUTING_KEY, + JSON.stringify(userDeletedIntegrationEvent), + ); } } diff --git a/src/modules/user/core/application/event-handlers/publish-message-when-user-is-updated.domain-event-handler.ts b/src/modules/user/core/application/event-handlers/publish-message-when-user-is-updated.domain-event-handler.ts index 90b51b1..745441a 100644 --- a/src/modules/user/core/application/event-handlers/publish-message-when-user-is-updated.domain-event-handler.ts +++ b/src/modules/user/core/application/event-handlers/publish-message-when-user-is-updated.domain-event-handler.ts @@ -2,7 +2,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; import { MessagePublisherPort } from '@mobicoop/ddd-library'; import { USER_MESSAGE_PUBLISHER } from '@modules/user/user.di-tokens'; -import { UserUpdatedDomainEvent } from '../../domain/events/user-updated.domain-events'; +import { UserUpdatedDomainEvent } from '../../domain/events/user-updated.domain-event'; +import { UserUpdatedIntegrationEvent } from '../events/user-updated.integration-event'; +import { USER_UPDATED_ROUTING_KEY } from '@modules/user/user.constants'; @Injectable() export class PublishMessageWhenUserIsUpdatedDomainEventHandler { @@ -13,6 +15,17 @@ export class PublishMessageWhenUserIsUpdatedDomainEventHandler { @OnEvent(UserUpdatedDomainEvent.name, { async: true, promisify: true }) async handle(event: UserUpdatedDomainEvent): Promise { - this.messagePublisher.publish('user.updated', JSON.stringify(event)); + const userUpdatedIntegrationEvent = new UserUpdatedIntegrationEvent({ + id: event.aggregateId, + firstName: event.firstName, + lastName: event.lastName, + email: event.email, + phone: event.phone, + metadata: event.metadata, + }); + this.messagePublisher.publish( + USER_UPDATED_ROUTING_KEY, + JSON.stringify(userUpdatedIntegrationEvent), + ); } } diff --git a/src/modules/user/core/application/events/user-created.integration-event.ts b/src/modules/user/core/application/events/user-created.integration-event.ts new file mode 100644 index 0000000..0e22107 --- /dev/null +++ b/src/modules/user/core/application/events/user-created.integration-event.ts @@ -0,0 +1,16 @@ +import { IntegrationEvent, IntegrationEventProps } from '@mobicoop/ddd-library'; + +export class UserCreatedIntegrationEvent extends IntegrationEvent { + readonly firstName: string; + readonly lastName: string; + readonly email: string; + readonly phone: string; + + constructor(props: IntegrationEventProps) { + super(props); + this.firstName = props.firstName; + this.lastName = props.lastName; + this.email = props.email; + this.phone = props.phone; + } +} diff --git a/src/modules/user/core/application/events/user-deleted.integration-event.ts b/src/modules/user/core/application/events/user-deleted.integration-event.ts new file mode 100644 index 0000000..f98d92c --- /dev/null +++ b/src/modules/user/core/application/events/user-deleted.integration-event.ts @@ -0,0 +1,7 @@ +import { IntegrationEvent, IntegrationEventProps } from '@mobicoop/ddd-library'; + +export class UserDeletedIntegrationEvent extends IntegrationEvent { + constructor(props: IntegrationEventProps) { + super(props); + } +} diff --git a/src/modules/user/core/application/events/user-updated.integration-event.ts b/src/modules/user/core/application/events/user-updated.integration-event.ts new file mode 100644 index 0000000..1cb6512 --- /dev/null +++ b/src/modules/user/core/application/events/user-updated.integration-event.ts @@ -0,0 +1,16 @@ +import { IntegrationEvent, IntegrationEventProps } from '@mobicoop/ddd-library'; + +export class UserUpdatedIntegrationEvent extends IntegrationEvent { + readonly firstName: string; + readonly lastName: string; + readonly email: string; + readonly phone: string; + + constructor(props: IntegrationEventProps) { + super(props); + this.firstName = props.firstName; + this.lastName = props.lastName; + this.email = props.email; + this.phone = props.phone; + } +} diff --git a/src/modules/user/core/domain/events/user-created.domain-events.ts b/src/modules/user/core/domain/events/user-created.domain-event.ts similarity index 100% rename from src/modules/user/core/domain/events/user-created.domain-events.ts rename to src/modules/user/core/domain/events/user-created.domain-event.ts diff --git a/src/modules/user/core/domain/events/user-updated.domain-events.ts b/src/modules/user/core/domain/events/user-updated.domain-event.ts similarity index 100% rename from src/modules/user/core/domain/events/user-updated.domain-events.ts rename to src/modules/user/core/domain/events/user-updated.domain-event.ts diff --git a/src/modules/user/core/domain/user.entity.ts b/src/modules/user/core/domain/user.entity.ts index 7c6448a..593bf43 100644 --- a/src/modules/user/core/domain/user.entity.ts +++ b/src/modules/user/core/domain/user.entity.ts @@ -1,8 +1,8 @@ import { AggregateRoot, AggregateID } from '@mobicoop/ddd-library'; import { v4 } from 'uuid'; import { CreateUserProps, UpdateUserProps, UserProps } from './user.types'; -import { UserCreatedDomainEvent } from './events/user-created.domain-events'; -import { UserUpdatedDomainEvent } from './events/user-updated.domain-events'; +import { UserCreatedDomainEvent } from './events/user-created.domain-event'; +import { UserUpdatedDomainEvent } from './events/user-updated.domain-event'; import { UserDeletedDomainEvent } from './events/user-deleted.domain-event'; export class UserEntity extends AggregateRoot { diff --git a/src/modules/user/infrastructure/user.repository.ts b/src/modules/user/infrastructure/user.repository.ts index 537961c..c40e67f 100644 --- a/src/modules/user/infrastructure/user.repository.ts +++ b/src/modules/user/infrastructure/user.repository.ts @@ -11,22 +11,27 @@ import { UserRepositoryPort } from '../core/application/ports/user.repository.po import { UserMapper } from '../user.mapper'; import { USER_MESSAGE_PUBLISHER } from '../user.di-tokens'; -export type UserModel = { +export type UserBaseModel = { uuid: string; firstName: string; lastName: string; email: string; phone: string; - createdAt: Date; - updatedAt: Date; }; +export type UserReadModel = UserBaseModel & { + createdAt?: Date; + updatedAt?: Date; +}; + +export type UserWriteModel = UserBaseModel; + /** * Repository is used for retrieving/saving domain entities * */ @Injectable() export class UserRepository - extends PrismaRepositoryBase + extends PrismaRepositoryBase implements UserRepositoryPort { constructor( diff --git a/src/modules/user/interface/grpc-controllers/update-user.grpc.controller.ts b/src/modules/user/interface/grpc-controllers/update-user.grpc.controller.ts index c5df8cb..17fd77f 100644 --- a/src/modules/user/interface/grpc-controllers/update-user.grpc.controller.ts +++ b/src/modules/user/interface/grpc-controllers/update-user.grpc.controller.ts @@ -25,11 +25,12 @@ import { export class UpdateUserGrpcController { constructor(private readonly commandBus: CommandBus) {} - @GrpcMethod('UserService', 'UpdateUser') + @GrpcMethod('UserService', 'Update') async updateUser(data: UpdateUserRequestDto): Promise { try { const aggregateID: AggregateID = await this.commandBus.execute( new UpdateUserCommand({ + id: data.id, firstName: data.firstName, lastName: data.lastName, email: data.email, diff --git a/src/modules/user/tests/unit/core/publish-message-when-user-is-created.domain-event-handler.spec.ts b/src/modules/user/tests/unit/core/publish-message-when-user-is-created.domain-event-handler.spec.ts index 0b03b0f..19ae79e 100644 --- a/src/modules/user/tests/unit/core/publish-message-when-user-is-created.domain-event-handler.spec.ts +++ b/src/modules/user/tests/unit/core/publish-message-when-user-is-created.domain-event-handler.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { PublishMessageWhenUserIsCreatedDomainEventHandler } from '@modules/user/core/application/event-handlers/publish-message-when-user-is-created.domain-event-handler'; import { USER_MESSAGE_PUBLISHER } from '@modules/user/user.di-tokens'; -import { UserCreatedDomainEvent } from '@modules/user/core/domain/events/user-created.domain-events'; +import { UserCreatedDomainEvent } from '@modules/user/core/domain/events/user-created.domain-event'; const mockMessagePublisher = { publish: jest.fn().mockImplementation(), @@ -48,7 +48,7 @@ describe('Publish message when user is created domain event handler', () => { expect(mockMessagePublisher.publish).toHaveBeenCalledTimes(1); expect(mockMessagePublisher.publish).toHaveBeenCalledWith( 'user.created', - '{"id":"some-domain-event-id","aggregateId":"some-aggregate-id","firstName":"John","lastName":"Doe","email":"john.doe@email.com","phone":"+33611223344","metadata":{"timestamp":1687928400000,"correlationId":"some-correlation-id"}}', + '{"id":"some-aggregate-id","metadata":{"correlationId":"some-correlation-id","timestamp":1687928400000},"firstName":"John","lastName":"Doe","email":"john.doe@email.com","phone":"+33611223344"}', ); }); }); diff --git a/src/modules/user/tests/unit/core/publish-message-when-user-is-deleted.domain-event-handler.spec.ts b/src/modules/user/tests/unit/core/publish-message-when-user-is-deleted.domain-event-handler.spec.ts index c4add5d..857cd9d 100644 --- a/src/modules/user/tests/unit/core/publish-message-when-user-is-deleted.domain-event-handler.spec.ts +++ b/src/modules/user/tests/unit/core/publish-message-when-user-is-deleted.domain-event-handler.spec.ts @@ -1,6 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; import { USER_MESSAGE_PUBLISHER } from '@modules/user/user.di-tokens'; -import { UserCreatedDomainEvent } from '@modules/user/core/domain/events/user-created.domain-events'; +import { UserCreatedDomainEvent } from '@modules/user/core/domain/events/user-created.domain-event'; import { PublishMessageWhenUserIsDeletedDomainEventHandler } from '@modules/user/core/application/event-handlers/publish-message-when-user-is-deleted.domain-event-handler'; const mockMessagePublisher = { @@ -48,7 +48,7 @@ describe('Publish message when user is deleted domain event handler', () => { expect(mockMessagePublisher.publish).toHaveBeenCalledTimes(1); expect(mockMessagePublisher.publish).toHaveBeenCalledWith( 'user.deleted', - '{"id":"some-domain-event-id","aggregateId":"some-aggregate-id","firstName":"John","lastName":"Doe","email":"john.doe@email.com","phone":"+33611223344","metadata":{"timestamp":1687928400000,"correlationId":"some-correlation-id"}}', + '{"id":"some-aggregate-id","metadata":{"correlationId":"some-correlation-id","timestamp":1687928400000}}', ); }); }); diff --git a/src/modules/user/tests/unit/core/publish-message-when-user-is-updated.domain-event-handler.spec.ts b/src/modules/user/tests/unit/core/publish-message-when-user-is-updated.domain-event-handler.spec.ts index af36963..9dd7c7b 100644 --- a/src/modules/user/tests/unit/core/publish-message-when-user-is-updated.domain-event-handler.spec.ts +++ b/src/modules/user/tests/unit/core/publish-message-when-user-is-updated.domain-event-handler.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { USER_MESSAGE_PUBLISHER } from '@modules/user/user.di-tokens'; import { PublishMessageWhenUserIsUpdatedDomainEventHandler } from '@modules/user/core/application/event-handlers/publish-message-when-user-is-updated.domain-event-handler'; -import { UserUpdatedDomainEvent } from '@modules/user/core/domain/events/user-updated.domain-events'; +import { UserUpdatedDomainEvent } from '@modules/user/core/domain/events/user-updated.domain-event'; const mockMessagePublisher = { publish: jest.fn().mockImplementation(), @@ -48,7 +48,7 @@ describe('Publish message when user is updated domain event handler', () => { expect(mockMessagePublisher.publish).toHaveBeenCalledTimes(1); expect(mockMessagePublisher.publish).toHaveBeenCalledWith( 'user.updated', - '{"id":"some-domain-event-id","aggregateId":"some-aggregate-id","firstName":"Jane","lastName":"Doe","email":"jane.doe@email.com","phone":"+33611223344","metadata":{"timestamp":1687928400000,"correlationId":"some-correlation-id"}}', + '{"id":"some-aggregate-id","metadata":{"correlationId":"some-correlation-id","timestamp":1687928400000},"firstName":"Jane","lastName":"Doe","email":"jane.doe@email.com","phone":"+33611223344"}', ); }); }); diff --git a/src/modules/user/tests/unit/core/user.entity.spec.ts b/src/modules/user/tests/unit/core/user.entity.spec.ts index 6a3d471..bd32b45 100644 --- a/src/modules/user/tests/unit/core/user.entity.spec.ts +++ b/src/modules/user/tests/unit/core/user.entity.spec.ts @@ -1,6 +1,6 @@ -import { UserCreatedDomainEvent } from '@modules/user/core/domain/events/user-created.domain-events'; +import { UserCreatedDomainEvent } from '@modules/user/core/domain/events/user-created.domain-event'; import { UserDeletedDomainEvent } from '@modules/user/core/domain/events/user-deleted.domain-event'; -import { UserUpdatedDomainEvent } from '@modules/user/core/domain/events/user-updated.domain-events'; +import { UserUpdatedDomainEvent } from '@modules/user/core/domain/events/user-updated.domain-event'; import { UserEntity } from '@modules/user/core/domain/user.entity'; import { CreateUserProps, diff --git a/src/modules/user/tests/unit/user.mapper.spec.ts b/src/modules/user/tests/unit/user.mapper.spec.ts index d4e3217..376e1a4 100644 --- a/src/modules/user/tests/unit/user.mapper.spec.ts +++ b/src/modules/user/tests/unit/user.mapper.spec.ts @@ -1,5 +1,8 @@ import { UserEntity } from '@modules/user/core/domain/user.entity'; -import { UserModel } from '@modules/user/infrastructure/user.repository'; +import { + UserReadModel, + UserWriteModel, +} from '@modules/user/infrastructure/user.repository'; import { UserResponseDto } from '@modules/user/interface/dtos/user.response.dto'; import { UserMapper } from '@modules/user/user.mapper'; import { Test } from '@nestjs/testing'; @@ -16,7 +19,7 @@ const userEntity: UserEntity = new UserEntity({ createdAt: now, updatedAt: now, }); -const userModel: UserModel = { +const userReadModel: UserReadModel = { uuid: 'c160cf8c-f057-4962-841f-3ad68346df44', firstName: 'John', lastName: 'Doe', @@ -41,12 +44,12 @@ describe('User Mapper', () => { }); it('should map domain entity to persistence data', async () => { - const mapped: UserModel = userMapper.toPersistence(userEntity); + const mapped: UserWriteModel = userMapper.toPersistence(userEntity); expect(mapped.lastName).toBe('Doe'); }); it('should map persisted data to domain entity', async () => { - const mapped: UserEntity = userMapper.toDomain(userModel); + const mapped: UserEntity = userMapper.toDomain(userReadModel); expect(mapped.getProps().firstName).toBe('John'); }); diff --git a/src/modules/user/user.constants.ts b/src/modules/user/user.constants.ts new file mode 100644 index 0000000..cf2e5f6 --- /dev/null +++ b/src/modules/user/user.constants.ts @@ -0,0 +1,3 @@ +export const USER_CREATED_ROUTING_KEY = 'user.created'; +export const USER_UPDATED_ROUTING_KEY = 'user.updated'; +export const USER_DELETED_ROUTING_KEY = 'user.deleted'; diff --git a/src/modules/user/user.mapper.ts b/src/modules/user/user.mapper.ts index b8034f4..ae6f848 100644 --- a/src/modules/user/user.mapper.ts +++ b/src/modules/user/user.mapper.ts @@ -1,7 +1,10 @@ import { Mapper } from '@mobicoop/ddd-library'; import { Injectable } from '@nestjs/common'; import { UserEntity } from './core/domain/user.entity'; -import { UserModel } from './infrastructure/user.repository'; +import { + UserReadModel, + UserWriteModel, +} from './infrastructure/user.repository'; import { UserResponseDto } from './interface/dtos/user.response.dto'; /** @@ -13,23 +16,21 @@ import { UserResponseDto } from './interface/dtos/user.response.dto'; @Injectable() export class UserMapper - implements Mapper + implements Mapper { - toPersistence = (entity: UserEntity): UserModel => { + toPersistence = (entity: UserEntity): UserWriteModel => { const copy = entity.getProps(); - const record: UserModel = { + const record: UserWriteModel = { uuid: copy.id, firstName: copy.firstName, lastName: copy.lastName, email: copy.email, phone: copy.phone, - createdAt: copy.createdAt, - updatedAt: copy.updatedAt, }; return record; }; - toDomain = (record: UserModel): UserEntity => { + toDomain = (record: UserReadModel): UserEntity => { const entity = new UserEntity({ id: record.uuid, createdAt: new Date(record.createdAt), @@ -53,12 +54,4 @@ export class UserMapper response.phone = props.phone; return response; }; - - /* ^ Data returned to the user is whitelisted to avoid leaks. - If a new property is added, like password or a - credit card number, it won't be returned - unless you specifically allow this. - (avoid blacklisting, which will return everything - but blacklisted items, which can lead to a data leak). - */ } diff --git a/src/modules/user/user.module.ts b/src/modules/user/user.module.ts index 15646bf..aa033c7 100644 --- a/src/modules/user/user.module.ts +++ b/src/modules/user/user.module.ts @@ -13,6 +13,13 @@ import { USER_MESSAGE_PUBLISHER, USER_REPOSITORY } from './user.di-tokens'; import { UserRepository } from './infrastructure/user.repository'; import { UserMapper } from './user.mapper'; import { PrismaService } from './infrastructure/prisma.service'; +import { DeleteUserGrpcController } from './interface/grpc-controllers/delete-user.grpc.controller'; +import { FindUserByIdGrpcController } from './interface/grpc-controllers/find-user-by-id.grpc.controller'; +import { DeleteUserService } from './core/application/commands/delete-user/delete-user.service'; +import { FindUserByIdQueryHandler } from './core/application/queries/find-user-by-id/find-user-by-id.query-handler'; +import { PublishMessageWhenUserIsCreatedDomainEventHandler } from './core/application/event-handlers/publish-message-when-user-is-created.domain-event-handler'; +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'; const imports = [ CqrsModule, @@ -30,9 +37,26 @@ const imports = [ }), ]; -const grpcControllers = [CreateUserGrpcController, UpdateUserGrpcController]; +const grpcControllers = [ + CreateUserGrpcController, + UpdateUserGrpcController, + DeleteUserGrpcController, + FindUserByIdGrpcController, +]; -const commandHandlers: Provider[] = [CreateUserService, UpdateUserService]; +const eventHandlers: Provider[] = [ + PublishMessageWhenUserIsCreatedDomainEventHandler, + PublishMessageWhenUserIsUpdatedDomainEventHandler, + PublishMessageWhenUserIsDeletedDomainEventHandler, +]; + +const commandHandlers: Provider[] = [ + CreateUserService, + UpdateUserService, + DeleteUserService, +]; + +const queryHandlers: Provider[] = [FindUserByIdQueryHandler]; const mappers: Provider[] = [UserMapper]; @@ -56,7 +80,9 @@ const orms: Provider[] = [PrismaService]; imports, controllers: [...grpcControllers], providers: [ + ...eventHandlers, ...commandHandlers, + ...queryHandlers, ...mappers, ...repositories, ...messagePublishers, From 3a02dfce3e77f08a5932731413909dde7a65bb3f Mon Sep 17 00:00:00 2001 From: sbriat Date: Mon, 24 Jul 2023 15:44:02 +0200 Subject: [PATCH 7/9] fix integration tests, update dddlibrary --- package-lock.json | 36 ++++++++++++++++--- package.json | 2 +- .../tests/integration/user.repository.spec.ts | 9 ++--- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7bac676..aef8efe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@grpc/proto-loader": "^0.7.4", "@liaoliaots/nestjs-redis": "^9.0.5", "@mobicoop/configuration-module": "^1.2.0", - "@mobicoop/ddd-library": "file:../../packages/dddlibrary", + "@mobicoop/ddd-library": "^1.0.0", "@mobicoop/health-module": "^2.0.0", "@mobicoop/message-broker-module": "^1.2.0", "@nestjs/cache-manager": "^1.0.0", @@ -1788,9 +1788,9 @@ } }, "node_modules/@mobicoop/ddd-library": { - "version": "0.3.0", - "resolved": "file:../../packages/dddlibrary", - "license": "AGPL", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@mobicoop/ddd-library/-/ddd-library-1.0.0.tgz", + "integrity": "sha512-uOF2n2VqgfVP4QldEPGMuR3VPn0U5+XXQw5CK1E/9IHXIgiqdmAnKHX5qUpcr29mKbU5QvQbBuIyMeQqCFVu+w==", "dependencies": { "@nestjs/event-emitter": "^1.4.2", "@nestjs/microservices": "^9.4.0", @@ -1832,6 +1832,34 @@ "@nestjs/common": "^9.4.2" } }, + "node_modules/@mobicoop/health-module/node_modules/@mobicoop/ddd-library": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@mobicoop/ddd-library/-/ddd-library-0.3.0.tgz", + "integrity": "sha512-MoUDqlrDmJkumCFSyW9FY2DLbguT4rytFrmBt9tVNCr2Es6nlz4Ml3HVBwJTZrlJFU79XmiUQ5WAO0MHJt+nAg==", + "dependencies": { + "@nestjs/event-emitter": "^1.4.2", + "@nestjs/microservices": "^9.4.0", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.0", + "uuid": "^9.0.0" + }, + "peerDependencies": { + "@nestjs/common": "^9.4.2" + } + }, + "node_modules/@mobicoop/health-module/node_modules/@nestjs/event-emitter": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@nestjs/event-emitter/-/event-emitter-1.4.2.tgz", + "integrity": "sha512-5mskPMS4KVH6LghC+NynfdmGiMCOOv9CdgVpuWGipLrJECv5KWc7vaW5o/9BYrcqPkN7Ted6CJ+O4AfsTiRlgw==", + "dependencies": { + "eventemitter2": "6.4.9" + }, + "peerDependencies": { + "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0", + "@nestjs/core": "^7.0.0 || ^8.0.0 || ^9.0.0", + "reflect-metadata": "^0.1.12" + } + }, "node_modules/@mobicoop/message-broker-module": { "version": "1.2.0", "license": "AGPL", diff --git a/package.json b/package.json index 21d1ea2..0f222b9 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@grpc/proto-loader": "^0.7.4", "@liaoliaots/nestjs-redis": "^9.0.5", "@mobicoop/configuration-module": "^1.2.0", - "@mobicoop/ddd-library": "file:../../packages/dddlibrary", + "@mobicoop/ddd-library": "^1.0.0", "@mobicoop/health-module": "^2.0.0", "@mobicoop/message-broker-module": "^1.2.0", "@nestjs/cache-manager": "^1.0.0", diff --git a/src/modules/user/tests/integration/user.repository.spec.ts b/src/modules/user/tests/integration/user.repository.spec.ts index 405e4e1..713a349 100644 --- a/src/modules/user/tests/integration/user.repository.spec.ts +++ b/src/modules/user/tests/integration/user.repository.spec.ts @@ -16,14 +16,13 @@ describe('User Repository', () => { let userRepository: UserRepository; const executeInsertCommand = async (table: string, object: any) => { - const command = `INSERT INTO ${table} ("${Object.keys(object).join( + const command = `INSERT INTO "${table}" ("${Object.keys(object).join( '","', - )}") VALUES (${Object.values(object).join(',')})`; - + )}") VALUES ('${Object.values(object).join("','")}')`; await prismaService.$executeRawUnsafe(command); }; const getSeed = (index: number, uuid: string): string => { - return `'${uuid.slice(0, -2)}${index.toString(16).padStart(2, '0')}'`; + return `${uuid.slice(0, -2)}${index.toString(16).padStart(2, '0')}`; }; const baseUuid = { @@ -38,6 +37,8 @@ describe('User Repository', () => { lastName: `Doe${i}`, email: `john.doe${i}@email.com`, phone: `+33611223344${i}`, + createdAt: '2023-07-24 13:07:05.000', + updatedAt: '2023-07-24 13:07:05.000', }; userToCreate.uuid = getSeed(i, baseUuid.uuid); await executeInsertCommand('user', userToCreate); From 248c1416565a9cf5589f29ea3c87b7b2d6214d00 Mon Sep 17 00:00:00 2001 From: sbriat Date: Mon, 24 Jul 2023 15:45:54 +0200 Subject: [PATCH 8/9] 1.0.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 aef8efe..90aedca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@mobicoop/user", - "version": "0.0.1", + "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@mobicoop/user", - "version": "0.0.1", + "version": "1.0.0", "license": "AGPL", "dependencies": { "@grpc/grpc-js": "^1.8.0", diff --git a/package.json b/package.json index 0f222b9..7c2b3af 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mobicoop/user", - "version": "0.0.1", + "version": "1.0.0", "description": "Mobicoop V3 User Service", "author": "sbriat", "private": true, From 048eba9423cfa307d5ad62157448be915c7d0319 Mon Sep 17 00:00:00 2001 From: sbriat Date: Mon, 24 Jul 2023 15:48:03 +0200 Subject: [PATCH 9/9] update readme --- README.md | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index d515345..20a2200 100644 --- a/README.md +++ b/README.md @@ -48,24 +48,15 @@ npm run migrate The app exposes the following [gRPC](https://grpc.io/) services : -- **FindByUuid** : find a user by its uuid +- **FindById** : find a user by its id ```json { - "uuid": "80126a61-d128-4f96-afdb-92e33c75a3e1" + "id": "80126a61-d128-4f96-afdb-92e33c75a3e1" } ``` -- **FindAll** : find all users; you can use pagination with `page` (default:_1_) and `perPage` (default:_10_) - - ```json - { - "page": 1, - "perPage": 10 - } - ``` - -- **Create** : create a user (note that uuid is optional, a uuid will be automatically attributed if it is not provided) +- **Create** : create a user ```json { @@ -82,15 +73,15 @@ The app exposes the following [gRPC](https://grpc.io/) services : { "firstName": "Jezabel-Katarina", "email": "jezabel-katarina.doe@email.com", - "uuid": "30f49838-3f24-42bb-a489-8ffb480173ae" + "id": "30f49838-3f24-42bb-a489-8ffb480173ae" } ``` -- **Delete** : delete a user by its uuid +- **Delete** : delete a user by its id ```json { - "uuid": "80126a61-d128-4f96-afdb-92e33c75a3e1" + "id": "80126a61-d128-4f96-afdb-92e33c75a3e1" } ``` @@ -102,7 +93,7 @@ As mentionned earlier, RabbitMQ messages are sent after these events : - **Update** (message : the updated user informations) -- **Delete** (message : the uuid of the deleted user) +- **Delete** (message : the id of the deleted user) Various messages are also sent for logging purpose.