diff --git a/.env.example b/.env.example index f340ddd..48ca2e6 100644 --- a/.env.example +++ b/.env.example @@ -1,14 +1,22 @@ -SERVER_PORT= +HTTP_PORT=3000 +HTTP_HOST=localhost +HTTP_PREFIX=api -POSTGRES_PORT= -POSTGRES_DB= -POSTGRES_USER= -POSTGRES_PASSWORD= +DB_HOST=events_node_db -JWT_ACCESS_SECRET= -JWT_ACCESS_EXPIRATION_TIME= +POSTGRES_PORT=5432 +POSTGRES_DB=example +POSTGRES_USER=example +POSTGRES_PASSWORD=example -SMTP_HOST= -SMTP_POTY= -SMTP_USER= -SMTP_PASS= \ No newline at end of file +JWT_ACCESS_SECRET=example +JWT_ACCESS_EXPIRATION_TIME=1d + +SMTP_HOST=sandbox.smtp.mailtrap.io +SMTP_PORT=2525 +SMTP_USER=example +SMTP_PASS=example +SMTP_FROM='"nest-modules" ' + +EMAIL_SUBJECT='Напоминание' +EMAIL_TEXT='У вас назначена встреча сегодня' \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..201fed5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +FROM node:20-alpine +WORKDIR /app +COPY package*.json ./ +RUN npm i +COPY . . +RUN npm run build +CMD ["sh", "-c", "npm run migration:run && npm start"] \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 538770c..55b567c 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -2,8 +2,19 @@ services: events_node_db: restart: always image: postgres:16-alpine - container_name: events_node_db + container_name: $DB_HOST env_file: - - path: ./.env + - path: ./.env ports: - - "$POSTGRES_PORT:5432" \ No newline at end of file + - '$POSTGRES_PORT:5432' + + events_node: + restart: always + build: . + container_name: events_node + env_file: + - path: ./.env + ports: + - '$HTTP_PORT:3000' + depends_on: + - events_node_db \ No newline at end of file diff --git a/nest-cli.json b/nest-cli.json index f9aa683..dfe879c 100644 --- a/nest-cli.json +++ b/nest-cli.json @@ -3,6 +3,14 @@ "collection": "@nestjs/schematics", "sourceRoot": "src", "compilerOptions": { + "plugins": [ + { + "name": "@nestjs/swagger", + "options": { + "classValidatorShim": true + } + } +], "deleteOutDir": true } } diff --git a/package-lock.json b/package-lock.json index 068e36a..5334d5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,9 +14,11 @@ "@nestjs/config": "^3.2.3", "@nestjs/core": "^10.0.0", "@nestjs/jwt": "^10.2.0", + "@nestjs/mapped-types": "^2.0.5", "@nestjs/passport": "^10.0.3", "@nestjs/platform-express": "^10.0.0", "@nestjs/schedule": "^4.1.0", + "@nestjs/swagger": "^7.4.0", "@nestjs/typeorm": "^10.0.2", "@types/passport-local": "^1.0.38", "argon2": "^0.40.3", @@ -26,7 +28,6 @@ "passport-jwt": "^4.0.1", "passport-local": "^1.0.0", "pg": "^8.12.0", - "pug": "^3.0.3", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1", "typeorm": "^0.3.20" @@ -215,9 +216,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", - "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", + "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -263,12 +264,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", - "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", + "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", "dev": true, "dependencies": { - "@babel/types": "^7.25.0", + "@babel/types": "^7.25.6", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -359,6 +360,7 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "devOptional": true, "engines": { "node": ">=6.9.0" } @@ -367,6 +369,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "devOptional": true, "engines": { "node": ">=6.9.0" } @@ -381,13 +384,13 @@ } }, "node_modules/@babel/helpers": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", - "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", + "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", "dev": true, "dependencies": { "@babel/template": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/types": "^7.25.6" }, "engines": { "node": ">=6.9.0" @@ -480,11 +483,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", - "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "devOptional": true, "dependencies": { - "@babel/types": "^7.25.2" + "@babel/types": "^7.25.6" }, "bin": { "parser": "bin/babel-parser.js" @@ -529,6 +533,36 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", + "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "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", @@ -640,6 +674,21 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "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", @@ -656,12 +705,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", - "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", + "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -671,9 +720,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.4.tgz", - "integrity": "sha512-DSgLeL/FNcpXuzav5wfYvHCGvynXkJbn3Zvc3823AEe9nPwW9IK4UoCSS5yGymmQzN0pCPvivtgS6/8U2kkm1w==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", + "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", "optional": true, "dependencies": { "regenerator-runtime": "^0.14.0" @@ -697,16 +746,16 @@ } }, "node_modules/@babel/traverse": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz", - "integrity": "sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", + "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/parser": "^7.25.3", + "@babel/generator": "^7.25.6", + "@babel/parser": "^7.25.6", "@babel/template": "^7.25.0", - "@babel/types": "^7.25.2", + "@babel/types": "^7.25.6", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -724,9 +773,10 @@ } }, "node_modules/@babel/types": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", - "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "devOptional": true, "dependencies": { "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", @@ -1708,6 +1758,11 @@ "node": ">=8" } }, + "node_modules/@microsoft/tsdoc": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz", + "integrity": "sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==" + }, "node_modules/@nestjs-modules/mailer": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@nestjs-modules/mailer/-/mailer-2.0.2.tgz", @@ -1742,48 +1797,10 @@ "pug": ">=3.0.1" } }, - "node_modules/@nestjs-modules/mailer/node_modules/glob": { - "version": "10.3.12", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", - "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.6", - "minimatch": "^9.0.1", - "minipass": "^7.0.4", - "path-scurry": "^1.10.2" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@nestjs-modules/mailer/node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, "node_modules/@nestjs/cli": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.4.2.tgz", - "integrity": "sha512-fQexIfLHfp6GUgX+CO4fOg+AEwV5ox/LHotQhyZi9wXUQDyIqS0NTTbumr//62EcX35qV4nU0359nYnuEdzG+A==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.4.5.tgz", + "integrity": "sha512-FP7Rh13u8aJbHe+zZ7hM0CC4785g9Pw4lz4r2TTgRtf0zTxSWMkJaPEwyjX8SK9oWK2GsYxl+fKpwVZNbmnj9A==", "dev": true, "dependencies": { "@angular-devkit/core": "17.3.8", @@ -1803,7 +1820,7 @@ "tsconfig-paths": "4.2.0", "tsconfig-paths-webpack-plugin": "4.1.0", "typescript": "5.3.3", - "webpack": "5.92.1", + "webpack": "5.94.0", "webpack-node-externals": "3.0.0" }, "bin": { @@ -1825,26 +1842,57 @@ } } }, - "node_modules/@nestjs/cli/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/@nestjs/cli/node_modules/glob": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", + "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=8.0.0" + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@nestjs/cli/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "node_modules/@nestjs/cli/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/@nestjs/cli/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=4.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@nestjs/cli/node_modules/typescript": { @@ -1860,57 +1908,10 @@ "node": ">=14.17" } }, - "node_modules/@nestjs/cli/node_modules/webpack": { - "version": "5.92.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.92.1.tgz", - "integrity": "sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-attributes": "^1.9.5", - "browserslist": "^4.21.10", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, "node_modules/@nestjs/common": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.3.10.tgz", - "integrity": "sha512-H8k0jZtxk1IdtErGDmxFRy0PfcOAUg41Prrqpx76DQusGGJjsaovs1zjXVD1rZWaVYchfT1uczJ6L4Kio10VNg==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.1.tgz", + "integrity": "sha512-4CkrDx0s4XuWqFjX8WvOFV7Y6RGJd0P2OBblkhZS7nwoctoSuW5pyEa8SWak6YHNGrHRpFb6ymm5Ai4LncwRVA==", "dependencies": { "iterare": "1.2.1", "tslib": "2.6.3", @@ -1950,9 +1951,9 @@ } }, "node_modules/@nestjs/core": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.3.10.tgz", - "integrity": "sha512-ZbQ4jovQyzHtCGCrzK5NdtW1SYO2fHSsgSY1+/9WdruYCUra+JDkWEXgZ4M3Hv480Dl3OXehAmY1wCOojeMyMQ==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.1.tgz", + "integrity": "sha512-9I1WdfOBCCHdUm+ClBJupOuZQS6UxzIWHIq6Vp1brAA5ZKl/Wq6BVwSsbnUJGBy3J3PM2XHmR0EQ4fwX3nR7lA==", "hasInstallScript": true, "dependencies": { "@nuxtjs/opencollective": "0.3.2", @@ -1998,6 +1999,25 @@ "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0" } }, + "node_modules/@nestjs/mapped-types": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.5.tgz", + "integrity": "sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg==", + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "class-transformer": "^0.4.0 || ^0.5.0", + "class-validator": "^0.13.0 || ^0.14.0", + "reflect-metadata": "^0.1.12 || ^0.2.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, "node_modules/@nestjs/passport": { "version": "10.0.3", "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-10.0.3.tgz", @@ -2008,9 +2028,9 @@ } }, "node_modules/@nestjs/platform-express": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.3.10.tgz", - "integrity": "sha512-wK2ow3CZI2KFqWeEpPmoR300OB6BcBLxARV1EiClJLCj4S1mZsoCmS0YWgpk3j1j6mo0SI8vNLi/cC2iZPEPQA==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.1.tgz", + "integrity": "sha512-ccfqIDAq/bg1ShLI5KGtaLaYGykuAdvCi57ohewH7eKJSIpWY1DQjbgKlFfXokALYUq1YOMGqjeZ244OWHfDQg==", "dependencies": { "body-parser": "1.20.2", "cors": "2.8.5", @@ -2040,22 +2060,10 @@ "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" } }, - "node_modules/@nestjs/schedule/node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/@nestjs/schematics": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-10.1.3.tgz", - "integrity": "sha512-aLJ4Nl/K/u6ZlgLa0NjKw5CuBOIgc6vudF42QvmGueu5FaMGM6IJrAuEvB5T2kr0PAfVwYmDFBBHCWdYhTw4Tg==", + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-10.1.4.tgz", + "integrity": "sha512-QpY8ez9cTvXXPr3/KBrtSgXQHMSV6BkOUYy2c2TTe6cBqriEdGnCYqGl8cnfrQl3632q3lveQPaZ/c127dHsEw==", "dev": true, "dependencies": { "@angular-devkit/core": "17.3.8", @@ -2074,10 +2082,42 @@ "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", "dev": true }, + "node_modules/@nestjs/swagger": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.4.0.tgz", + "integrity": "sha512-dCiwKkRxcR7dZs5jtrGspBAe/nqJd1AYzOBTzw9iCdbq3BGrLpwokelk6lFZPe4twpTsPQqzNKBwKzVbI6AR/g==", + "dependencies": { + "@microsoft/tsdoc": "^0.15.0", + "@nestjs/mapped-types": "2.0.5", + "js-yaml": "4.1.0", + "lodash": "4.17.21", + "path-to-regexp": "3.2.0", + "swagger-ui-dist": "5.17.14" + }, + "peerDependencies": { + "@fastify/static": "^6.0.0 || ^7.0.0", + "@nestjs/common": "^9.0.0 || ^10.0.0", + "@nestjs/core": "^9.0.0 || ^10.0.0", + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12 || ^0.2.0" + }, + "peerDependenciesMeta": { + "@fastify/static": { + "optional": true + }, + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, "node_modules/@nestjs/testing": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.3.10.tgz", - "integrity": "sha512-i3HAtVQJijxNxJq1k39aelyJlyEIBRONys7IipH/4r8W0J+M1V+y5EKDOyi4j1SdNSb/vmNyWpZ2/ewZjl3kRA==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.1.tgz", + "integrity": "sha512-pR+su5+YGqCLH0RhhVkPowQK7FCORU0/PWAywPK7LScAOtD67ZoviZ7hAU4vnGdwkg4HCB0D7W8Bkg19CGU8Xw==", "dev": true, "dependencies": { "tslib": "2.6.3" @@ -2116,6 +2156,18 @@ "typeorm": "^0.3.0" } }, + "node_modules/@nestjs/typeorm/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2203,6 +2255,12 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true + }, "node_modules/@selderee/plugin-htmlparser2": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz", @@ -2339,26 +2397,6 @@ "integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==", "optional": true }, - "node_modules/@types/eslint": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", - "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -2487,11 +2525,11 @@ "optional": true }, "node_modules/@types/node": { - "version": "20.14.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.14.tgz", - "integrity": "sha512-d64f00982fS9YoOgJkAMolK7MN8Iq3TDdVjchbYHdEmjth/DHowx82GnoA+tVUAN+7vxfYUgAzi+JXbKNd2SDQ==", + "version": "20.16.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.5.tgz", + "integrity": "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "node_modules/@types/passport": { @@ -2579,9 +2617,9 @@ "dev": true }, "node_modules/@types/superagent": { - "version": "8.1.8", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.8.tgz", - "integrity": "sha512-nTqHJ2OTa7PFEpLahzSEEeFeqbMpmcN7OeayiOc7v+xk+/vyTKljRe+o4MPqSnPeRCMvtxuLG+5QqluUVQJOnA==", + "version": "8.1.9", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz", + "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==", "dev": true, "dependencies": { "@types/cookiejar": "^2.1.5", @@ -2601,14 +2639,14 @@ } }, "node_modules/@types/validator": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.0.tgz", - "integrity": "sha512-nH45Lk7oPIJ1RVOF6JgFI6Dy0QpHEzq4QecZhvguxYPDwT8c93prCMqAtiIttm39voZ+DDR+qkNnMpJmMBRqag==" + "version": "13.12.1", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.1.tgz", + "integrity": "sha512-w0URwf7BQb0rD/EuiG12KP0bailHKHP5YVviJG9zw3ykAokL0TuxU2TUqMB7EwZ59bDHYdeTIvjI5m0S7qHfOA==" }, "node_modules/@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -3231,8 +3269,7 @@ "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==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/array-buffer-byte-length": { "version": "1.0.1", @@ -3371,17 +3408,19 @@ "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "devOptional": true }, "node_modules/assert-never": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.3.0.tgz", - "integrity": "sha512-9Z3vxQ+berkL/JJo0dK+EY3Lp0s3NtSnP3VCLsh5HDcZPrh0M+KQRK5sWhUeyPPH+/RCxZqOxLMR+YC6vlviEQ==" + "integrity": "sha512-9Z3vxQ+berkL/JJo0dK+EY3Lp0s3NtSnP3VCLsh5HDcZPrh0M+KQRK5sWhUeyPPH+/RCxZqOxLMR+YC6vlviEQ==", + "optional": true }, "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "devOptional": true }, "node_modules/asynckit": { @@ -3483,23 +3522,26 @@ } }, "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==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", "dev": true, "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0" @@ -3525,6 +3567,7 @@ "version": "3.0.0-canary-5", "resolved": "https://registry.npmjs.org/babel-walk/-/babel-walk-3.0.0-canary-5.tgz", "integrity": "sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==", + "optional": true, "dependencies": { "@babel/types": "^7.9.6" }, @@ -3808,9 +3851,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001647", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001647.tgz", - "integrity": "sha512-n83xdNiyeNcHpzWY+1aFbqCK7LuLfBricc4+alSQL2Xb6OR3XpnQAmlDG+pQcdTfiHRuLcQ96VOfrPSGiNJYSg==", + "version": "1.0.30001658", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001658.tgz", + "integrity": "sha512-N2YVqWbJELVdrnsW5p+apoQyYt51aBMSsBZki1XZEfeBCexcM/sf4xiAHcXQBkuOwJBXtWF7aW1sYX6tKebPHw==", "dev": true, "funding": [ { @@ -3855,6 +3898,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", "integrity": "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==", + "optional": true, "dependencies": { "is-regex": "^1.0.3" } @@ -3903,31 +3947,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/cheerio/node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "optional": true, - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/cheerio/node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", - "optional": true, - "dependencies": { - "domhandler": "^5.0.2", - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -3977,9 +3996,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", - "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.0.tgz", + "integrity": "sha512-N1NGmowPlGBLsOZLPvm48StN04V4YvQRL0i6b7ctrVY3epjP/ct7hFLOItz6pDIvRjwpfPxi52a2UWV2ziir8g==", "dev": true }, "node_modules/class-transformer": { @@ -4060,6 +4079,24 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/cli-highlight/node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + }, + "node_modules/cli-highlight/node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/cli-highlight/node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, "node_modules/cli-highlight/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -4292,6 +4329,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", "integrity": "sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==", + "optional": true, "dependencies": { "@babel/parser": "^7.6.0", "@babel/types": "^7.6.1" @@ -4513,16 +4551,16 @@ } }, "node_modules/dayjs": { - "version": "1.11.12", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz", - "integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==" + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==" }, "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -4736,7 +4774,8 @@ "node_modules/doctypes": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", - "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==" + "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==", + "optional": true }, "node_modules/dom-serializer": { "version": "2.0.0", @@ -4888,9 +4927,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.4.tgz", - "integrity": "sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==", + "version": "1.5.18", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.18.tgz", + "integrity": "sha512-1OfuVACu+zKlmjsNdcJuVQuVE61sZOLbNM4JAQ1Rvh6EOj0/EUKhMJjRH73InPlXSh8HIJk1cVZ8pyOV/FMdUQ==", "dev": true }, "node_modules/emittery": { @@ -5099,9 +5138,9 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "engines": { "node": ">=6" } @@ -5234,9 +5273,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.2.tgz", - "integrity": "sha512-3XnC5fDyc8M4J2E8pt8pmSVRX2M+5yWMCfI/kDZwauQeFgzQOuhcRBFKjTeJagqgk4sFKxe1mvNVnaWwImx/Tg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.11.0.tgz", + "integrity": "sha512-gbBE5Hitek/oG6MUVj6sFuzEjA/ClzNflVrLovHi/JgLdC7fiN5gLAY1WIPW1a0V5I999MnsrvVrCOGmmVqDBQ==", "dev": true, "dependencies": { "debug": "^3.2.7" @@ -5260,26 +5299,27 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.30.0.tgz", + "integrity": "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==", "dev": true, "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", "array.prototype.flat": "^1.3.2", "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", + "eslint-module-utils": "^2.9.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", "semver": "^6.3.1", "tsconfig-paths": "^3.15.0" }, @@ -5962,9 +6002,9 @@ } }, "node_modules/foreground-child": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", - "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -6232,22 +6272,21 @@ } }, "node_modules/glob": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", - "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" }, "bin": { "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -6271,20 +6310,6 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, - "node_modules/glob/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/globals": { "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", @@ -6453,6 +6478,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "devOptional": true, "dependencies": { "has-symbols": "^1.0.3" }, @@ -6623,9 +6649,9 @@ ] }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "engines": { "node": ">= 4" @@ -6820,9 +6846,10 @@ } }, "node_modules/is-core-module": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", - "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "devOptional": true, "dependencies": { "hasown": "^2.0.2" }, @@ -6882,6 +6909,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-4.0.0.tgz", "integrity": "sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==", + "optional": true, "dependencies": { "acorn": "^7.1.1", "object-assign": "^4.1.1" @@ -6891,6 +6919,7 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "optional": true, "bin": { "acorn": "bin/acorn" }, @@ -6994,12 +7023,14 @@ "node_modules/is-promise": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "optional": true }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "devOptional": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -7213,12 +7244,15 @@ } }, "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", "dependencies": { "@isaacs/cliui": "^8.0.2" }, + "engines": { + "node": ">=14" + }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -7971,7 +8005,8 @@ "node_modules/js-stringify": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", - "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==" + "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==", + "optional": true }, "node_modules/js-tokens": { "version": "4.0.0", @@ -7983,7 +8018,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -8084,6 +8118,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==", + "optional": true, "dependencies": { "is-promise": "^2.0.0", "promise": "^7.0.1" @@ -8218,9 +8253,9 @@ } }, "node_modules/libphonenumber-js": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.5.tgz", - "integrity": "sha512-TwHR5BZxGRODtAfz03szucAkjT5OArXr+94SMtAM2pYXIlQNVMrxvb6uSCbnaJJV6QXEyICk7+l6QPgn72WHhg==" + "version": "1.11.7", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.7.tgz", + "integrity": "sha512-x2xON4/Qg2bRIS11KIN9yCNYUjhtiEjNyptjX0mX+pyKHecxuJVLIpfX1lq9ZD6CrC/rB+y4GBi18c6CEcUR+A==" }, "node_modules/libqp": { "version": "2.1.0", @@ -8244,9 +8279,9 @@ } }, "node_modules/liquidjs": { - "version": "10.16.4", - "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.16.4.tgz", - "integrity": "sha512-5kK5HRZng6crSedS11D1h9Od8pYB5wjWjvJIlbhLVS7n+ITWzQervv27jx+7MkOS2KYfAEhwlEinTsTn4Ae5WQ==", + "version": "10.16.7", + "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.16.7.tgz", + "integrity": "sha512-vjlBDyPxFgUc6vJB+TbAMcxKKKcm4Ee0rj9Je9lcG1I0lr9xvtHgB/ZdNMNAgsPUvJLkLfdrKRd+KzQ5opPfNg==", "optional": true, "dependencies": { "commander": "^10.0.0" @@ -8581,9 +8616,9 @@ } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { "braces": "^3.0.3", @@ -9111,9 +9146,9 @@ } }, "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==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/multer": { "version": "1.4.4-lts.1", @@ -9226,9 +9261,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", - "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.2.tgz", + "integrity": "sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw==", "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", @@ -9248,9 +9283,9 @@ "dev": true }, "node_modules/nodemailer": { - "version": "6.9.14", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.14.tgz", - "integrity": "sha512-Dobp/ebDKBvz91sbtRKhcznLThrKxKt97GI2FAlAyy+fk19j73Uz3sBXolVtmcXjaorivqsbbbjDY+Jkt4/bQA==", + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.15.tgz", + "integrity": "sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==", "engines": { "node": ">=6.0.0" } @@ -9593,7 +9628,8 @@ "node_modules/package-json-from-dist": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==" + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true }, "node_modules/param-case": { "version": "2.1.1", @@ -9635,23 +9671,30 @@ } }, "node_modules/parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "optional": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } }, "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "optional": true, "dependencies": { - "parse5": "^6.0.1" + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - }, "node_modules/parseley": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz", @@ -9748,7 +9791,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==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "devOptional": true }, "node_modules/path-scurry": { "version": "1.11.1", @@ -9881,9 +9925,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true }, "node_modules/picomatch": { @@ -10109,6 +10153,19 @@ "node": ">=14" } }, + "node_modules/preview-email/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -10118,6 +10175,7 @@ "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "optional": true, "dependencies": { "asap": "~2.0.3" } @@ -10157,6 +10215,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.3.tgz", "integrity": "sha512-uBi6kmc9f3SZ3PXxqcHiUZLmIXgfgWooKWXcwSGwQd2Zi5Rb0bT14+8CJjJgI8AB+nndLaNgHGrcc6bPIB665g==", + "optional": true, "dependencies": { "pug-code-gen": "^3.0.3", "pug-filters": "^4.0.0", @@ -10172,6 +10231,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-3.0.0.tgz", "integrity": "sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==", + "optional": true, "dependencies": { "constantinople": "^4.0.1", "js-stringify": "^1.0.2", @@ -10182,6 +10242,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-3.0.3.tgz", "integrity": "sha512-cYQg0JW0w32Ux+XTeZnBEeuWrAY7/HNE6TWnhiHGnnRYlCgyAUPoyh9KzCMa9WhcJlJ1AtQqpEYHc+vbCzA+Aw==", + "optional": true, "dependencies": { "constantinople": "^4.0.1", "doctypes": "^1.1.0", @@ -10196,12 +10257,14 @@ "node_modules/pug-error": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-2.1.0.tgz", - "integrity": "sha512-lv7sU9e5Jk8IeUheHata6/UThZ7RK2jnaaNztxfPYUY+VxZyk/ePVaNZ/vwmH8WqGvDz3LrNYt/+gA55NDg6Pg==" + "integrity": "sha512-lv7sU9e5Jk8IeUheHata6/UThZ7RK2jnaaNztxfPYUY+VxZyk/ePVaNZ/vwmH8WqGvDz3LrNYt/+gA55NDg6Pg==", + "optional": true }, "node_modules/pug-filters": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-4.0.0.tgz", "integrity": "sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==", + "optional": true, "dependencies": { "constantinople": "^4.0.1", "jstransformer": "1.0.0", @@ -10214,6 +10277,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-5.0.1.tgz", "integrity": "sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==", + "optional": true, "dependencies": { "character-parser": "^2.2.0", "is-expression": "^4.0.0", @@ -10224,6 +10288,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-4.0.0.tgz", "integrity": "sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==", + "optional": true, "dependencies": { "pug-error": "^2.0.0", "pug-walk": "^2.0.0" @@ -10233,6 +10298,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-3.0.0.tgz", "integrity": "sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==", + "optional": true, "dependencies": { "object-assign": "^4.1.1", "pug-walk": "^2.0.0" @@ -10242,6 +10308,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-6.0.0.tgz", "integrity": "sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==", + "optional": true, "dependencies": { "pug-error": "^2.0.0", "token-stream": "1.0.0" @@ -10250,12 +10317,14 @@ "node_modules/pug-runtime": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-3.0.1.tgz", - "integrity": "sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==" + "integrity": "sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==", + "optional": true }, "node_modules/pug-strip-comments": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz", "integrity": "sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==", + "optional": true, "dependencies": { "pug-error": "^2.0.0" } @@ -10263,7 +10332,8 @@ "node_modules/pug-walk": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-2.0.0.tgz", - "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==" + "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==", + "optional": true }, "node_modules/punycode": { "version": "2.3.1", @@ -10505,6 +10575,7 @@ "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "devOptional": true, "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -10994,11 +11065,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "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==" - }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -11446,6 +11512,7 @@ "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==", + "devOptional": true, "engines": { "node": ">= 0.4" }, @@ -11453,6 +11520,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/swagger-ui-dist": { + "version": "5.17.14", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz", + "integrity": "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==" + }, "node_modules/symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", @@ -11488,9 +11560,9 @@ } }, "node_modules/terser": { - "version": "5.31.3", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.3.tgz", - "integrity": "sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==", + "version": "5.31.6", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz", + "integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -11694,6 +11766,7 @@ "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==", + "devOptional": true, "engines": { "node": ">=4" } @@ -11721,7 +11794,8 @@ "node_modules/token-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-1.0.0.tgz", - "integrity": "sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==" + "integrity": "sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==", + "optional": true }, "node_modules/tr46": { "version": "0.0.3", @@ -11750,20 +11824,20 @@ } }, "node_modules/ts-jest": { - "version": "29.2.4", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.4.tgz", - "integrity": "sha512-3d6tgDyhCI29HlpwIq87sNuI+3Q6GLTTCeYRHCs7vDz+/3GCMwEtV9jezLyl4ZtnBgx00I7hm8PCP8cTksMGrw==", + "version": "29.2.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", + "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", "dev": true, "dependencies": { - "bs-logger": "0.x", + "bs-logger": "^0.2.6", "ejs": "^3.1.10", - "fast-json-stable-stringify": "2.x", + "fast-json-stable-stringify": "^2.1.0", "jest-util": "^29.0.0", "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.6.3", + "yargs-parser": "^21.1.1" }, "bin": { "ts-jest": "cli.js" @@ -12169,6 +12243,18 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/typeorm/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/typescript": { "version": "5.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", @@ -12189,9 +12275,9 @@ "optional": true }, "node_modules/uglify-js": { - "version": "3.19.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.2.tgz", - "integrity": "sha512-S8KA6DDI47nQXJSi2ctQ629YzwOVs+bQML6DAtvy0wgNdpi+0ySpQK0g2pxBq2xfF2z3YCscu7NNA8nXT9PlIQ==", + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -12227,9 +12313,9 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" }, "node_modules/universalify": { "version": "2.0.1", @@ -12307,9 +12393,9 @@ } }, "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -12367,6 +12453,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "optional": true, "engines": { "node": ">=0.10.0" } @@ -12381,9 +12468,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "dev": true, "dependencies": { "glob-to-regexp": "^0.4.1", @@ -12534,13 +12621,11 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/webpack": { - "version": "5.93.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", - "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", + "version": "5.94.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", + "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", "dev": true, - "peer": true, "dependencies": { - "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", "@webassemblyjs/wasm-edit": "^1.12.1", @@ -12549,7 +12634,7 @@ "acorn-import-attributes": "^1.9.5", "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", @@ -12604,7 +12689,6 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, - "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -12618,7 +12702,6 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "peer": true, "engines": { "node": ">=4.0" } @@ -12685,6 +12768,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/with/-/with-7.0.2.tgz", "integrity": "sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==", + "optional": true, "dependencies": { "@babel/parser": "^7.9.6", "@babel/types": "^7.9.6", diff --git a/package.json b/package.json index 83e4ea1..dabcc95 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,9 @@ "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "typeorm": "ts-node ./node_modules/typeorm/cli", "migration:create": "npm run typeorm -- migration:create ./src/migrations/$npm_config_name", - "migration:generate": "npm run typeorm -- -d src/config/typeorm.config.ts migration:generate ./src/migrations/$npm_config_name", - "migration:run": "npm run typeorm migration:run -- -d src/config/typeorm.config.ts", - "migration:revert": "npm run typeorm -- -d src/config/typeorm.config.ts migration:revert", + "migration:generate": "npm run typeorm -- -d src/common/config/typeorm.config.ts migration:generate ./src/migrations/$npm_config_name", + "migration:run": "npm run typeorm migration:run -- -d src/common/config/typeorm.config.ts", + "migration:revert": "npm run typeorm -- -d src/common/config/typeorm.config.ts migration:revert", "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", @@ -30,9 +30,11 @@ "@nestjs/config": "^3.2.3", "@nestjs/core": "^10.0.0", "@nestjs/jwt": "^10.2.0", + "@nestjs/mapped-types": "^2.0.5", "@nestjs/passport": "^10.0.3", "@nestjs/platform-express": "^10.0.0", "@nestjs/schedule": "^4.1.0", + "@nestjs/swagger": "^7.4.0", "@nestjs/typeorm": "^10.0.2", "@types/passport-local": "^1.0.38", "argon2": "^0.40.3", @@ -42,7 +44,6 @@ "passport-jwt": "^4.0.1", "passport-local": "^1.0.0", "pg": "^8.12.0", - "pug": "^3.0.3", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1", "typeorm": "^0.3.20" diff --git a/src/config/typeorm.config.ts b/src/common/config/typeorm.config.ts similarity index 71% rename from src/config/typeorm.config.ts rename to src/common/config/typeorm.config.ts index 2ed22a4..a8f1b1e 100644 --- a/src/config/typeorm.config.ts +++ b/src/common/config/typeorm.config.ts @@ -11,10 +11,11 @@ config(); const configService = new ConfigService(); const databaseConfig = { type: 'postgres' as const, - port: configService.get('POSTGRES_PORT'), - database: configService.get('POSTGRES_DB'), - username: configService.get('POSTGRES_USER'), - password: configService.get('POSTGRES_PASSWORD'), + host: configService.getOrThrow('DB_HOST'), + port: configService.getOrThrow('POSTGRES_PORT'), + database: configService.getOrThrow('POSTGRES_DB'), + username: configService.getOrThrow('POSTGRES_USER'), + password: configService.getOrThrow('POSTGRES_PASSWORD'), autoLoadEntities: true, synchronize: false, entities: ['dist/**/*.entity.js'], diff --git a/src/config/decorators/user.decorator.ts b/src/common/decorators/user.decorator.ts similarity index 100% rename from src/config/decorators/user.decorator.ts rename to src/common/decorators/user.decorator.ts diff --git a/src/module/auth/strategies/types/auth.types.ts b/src/common/types/auth.types.ts similarity index 50% rename from src/module/auth/strategies/types/auth.types.ts rename to src/common/types/auth.types.ts index 68a8171..d86ffd4 100644 --- a/src/module/auth/strategies/types/auth.types.ts +++ b/src/common/types/auth.types.ts @@ -1,4 +1,4 @@ -import { UserRole } from 'src/config/types/entity.enums'; +import { UserRole } from 'src/common/types/entity.enums'; export type Payload = { id: number; diff --git a/src/config/types/entity.enums.ts b/src/common/types/entity.enums.ts similarity index 100% rename from src/config/types/entity.enums.ts rename to src/common/types/entity.enums.ts diff --git a/src/common/utils/parse-id.ts b/src/common/utils/parse-id.ts new file mode 100644 index 0000000..2485553 --- /dev/null +++ b/src/common/utils/parse-id.ts @@ -0,0 +1,9 @@ +import { BadRequestException } from '@nestjs/common'; + +export function parseId(id: string) { + const parsedId = parseInt(id, 10); + if (isNaN(parsedId)) { + throw new BadRequestException(); + } + return parsedId; +} diff --git a/src/main.ts b/src/main.ts index 50c6e67..a19ed7c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,16 +1,29 @@ import { ClassSerializerInterceptor, ValidationPipe } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { NestFactory, Reflector } from '@nestjs/core'; +import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { AppModule } from './module/app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); const configService = app.get(ConfigService); - const PORT = configService.get('SERVER_PORT'); + const PORT = configService.getOrThrow('HTTP_PORT'); app.useGlobalPipes(new ValidationPipe()); app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector))); + + const configSwagger = new DocumentBuilder() + .setTitle('Events service') + .setDescription('API Documentation') + .setVersion('1.0') + .build(); + const document = SwaggerModule.createDocument(app, configSwagger); + SwaggerModule.setup( + `${configService.getOrThrow('HTTP_PREFIX')}/docs`, + app, + document, + ); await app.listen(PORT); } bootstrap(); diff --git a/src/migrations/1725817595096-Fix.ts b/src/migrations/1725817595096-Fix.ts new file mode 100644 index 0000000..a6a59e7 --- /dev/null +++ b/src/migrations/1725817595096-Fix.ts @@ -0,0 +1,29 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class Fix1725817595096 implements MigrationInterface { + name = 'Fix1725817595096'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user" ALTER COLUMN "location" SET NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "user" ALTER COLUMN "fullname" SET NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "event" ALTER COLUMN "description" DROP NOT NULL`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "event" ALTER COLUMN "description" SET NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "user" ALTER COLUMN "fullname" DROP NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "user" ALTER COLUMN "location" DROP NOT NULL`, + ); + } +} diff --git a/src/module/app.module.ts b/src/module/app.module.ts index 4b1073f..0d96580 100644 --- a/src/module/app.module.ts +++ b/src/module/app.module.ts @@ -1,7 +1,6 @@ import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { typeOrmAsyncConfig } from 'src/config/typeorm.config'; import { AuthModule } from './auth/auth.module'; import { BookingModule } from './booking/booking.module'; @@ -9,6 +8,7 @@ import { EventModule } from './event/event.module'; import { MailModule } from './mail/mail.module'; import { SchedulerModule } from './scheduler/scheduler.module'; import { UserModule } from './user/user.module'; +import { typeOrmAsyncConfig } from '../common/config/typeorm.config'; @Module({ imports: [ diff --git a/src/module/auth/auth.controller.ts b/src/module/auth/auth.controller.ts index 340b89a..efd6459 100644 --- a/src/module/auth/auth.controller.ts +++ b/src/module/auth/auth.controller.ts @@ -1,12 +1,13 @@ -import { Body, Controller, Get, Post, UseGuards } from '@nestjs/common'; -import { UserFromRequest } from 'src/config/decorators/user.decorator'; +import { Body, Controller, Post, UseGuards } from '@nestjs/common'; +import { ApiTags } from '@nestjs/swagger'; import { AuthService } from './auth.service'; import { RegisterAuthDto } from './dto/register.auth.dto'; -import { AccessTokenGuard } from './guards/access-token.guard'; import { LocalGuard } from './guards/local.guard'; +import { UserFromRequest } from '../../common/decorators/user.decorator'; import { User } from '../user/entity/user.entity'; +@ApiTags('Auth') @Controller('auth') export class AuthController { constructor(private readonly authService: AuthService) {} @@ -21,10 +22,4 @@ export class AuthController { login(@UserFromRequest() user: User) { return this.authService.login(user); } - - @UseGuards(AccessTokenGuard) - @Get('logout') - logout() { - return 1; - } } diff --git a/src/module/auth/auth.service.ts b/src/module/auth/auth.service.ts index ee23eaa..be847eb 100644 --- a/src/module/auth/auth.service.ts +++ b/src/module/auth/auth.service.ts @@ -2,11 +2,11 @@ import { Injectable, UnauthorizedException } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { JwtService } from '@nestjs/jwt'; import { verify } from 'argon2'; -import { UserRepository } from 'src/module/user/user.repository'; import { RegisterAuthDto } from './dto/register.auth.dto'; -import { Payload } from './strategies/types/auth.types'; +import { Payload } from '../../common/types/auth.types'; import { User } from '../user/entity/user.entity'; +import { UserRepository } from '../user/user.repository'; import { UserService } from '../user/user.service'; @Injectable() @@ -42,8 +42,8 @@ export class AuthService { private async getToken(user: User) { const payload: Payload = { id: user.id, role: user.role }; const accessToken = await this.jwtService.signAsync(payload, { - secret: this.configService.get('JWT_ACCESS_SECRET'), - expiresIn: this.configService.get('JWT_ACCESS_EXPIRATION_TIME'), + secret: this.configService.getOrThrow('JWT_ACCESS_SECRET'), + expiresIn: this.configService.getOrThrow('JWT_ACCESS_EXPIRATION_TIME'), }); return accessToken; } diff --git a/src/module/auth/dto/register.auth.dto.ts b/src/module/auth/dto/register.auth.dto.ts index ce0075f..29293e9 100644 --- a/src/module/auth/dto/register.auth.dto.ts +++ b/src/module/auth/dto/register.auth.dto.ts @@ -1,3 +1,3 @@ -import { CreateUserDto } from 'src/module/user/dto/create-user.dto'; +import { CreateUserDto } from '../../user/dto/create-user.dto'; export class RegisterAuthDto extends CreateUserDto {} diff --git a/src/module/auth/strategies/access-token.strategy.ts b/src/module/auth/strategies/access-token.strategy.ts index c7bea61..d8ce9f7 100644 --- a/src/module/auth/strategies/access-token.strategy.ts +++ b/src/module/auth/strategies/access-token.strategy.ts @@ -3,7 +3,7 @@ import { ConfigService } from '@nestjs/config'; import { PassportStrategy } from '@nestjs/passport'; import { ExtractJwt, Strategy } from 'passport-jwt'; -import { Payload } from './types/auth.types'; +import { Payload } from '../../../common/types/auth.types'; @Injectable() export class AccessTokenStrategy extends PassportStrategy(Strategy) { @@ -11,7 +11,7 @@ export class AccessTokenStrategy extends PassportStrategy(Strategy) { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), ignoreExpiration: false, - secretOrKey: configService.get('JWT_ACCESS_SECRET'), + secretOrKey: configService.getOrThrow('JWT_ACCESS_SECRET'), }); } diff --git a/src/module/booking/booking.controller.ts b/src/module/booking/booking.controller.ts index 5f25d4e..e795318 100644 --- a/src/module/booking/booking.controller.ts +++ b/src/module/booking/booking.controller.ts @@ -8,12 +8,14 @@ import { Post, UseGuards, } from '@nestjs/common'; -import { UserFromRequest } from 'src/config/decorators/user.decorator'; +import { ApiTags } from '@nestjs/swagger'; import { BookingService } from './booking.service'; +import { UserFromRequest } from '../../common/decorators/user.decorator'; import { AccessTokenGuard } from '../auth/guards/access-token.guard'; import { User } from '../user/entity/user.entity'; +@ApiTags('Booking') @Controller() export class BookingController { constructor(private readonly bookingService: BookingService) {} diff --git a/src/module/booking/booking.module.ts b/src/module/booking/booking.module.ts index 5fbbc51..21ae76d 100644 --- a/src/module/booking/booking.module.ts +++ b/src/module/booking/booking.module.ts @@ -2,6 +2,7 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { BookingController } from './booking.controller'; +import { BookingRepository } from './booking.repository'; import { BookingService } from './booking.service'; import { Booking } from './entity/booking.entity'; import { EventModule } from '../event/event.module'; @@ -9,7 +10,7 @@ import { EventModule } from '../event/event.module'; @Module({ imports: [TypeOrmModule.forFeature([Booking]), EventModule], controllers: [BookingController], - providers: [BookingService], + providers: [BookingService, BookingRepository], exports: [], }) export class BookingModule {} diff --git a/src/module/booking/booking.repository.ts b/src/module/booking/booking.repository.ts index 77d5d8d..5db765c 100644 --- a/src/module/booking/booking.repository.ts +++ b/src/module/booking/booking.repository.ts @@ -1,17 +1,36 @@ import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; +import { Repository, Equal, DeepPartial } from 'typeorm'; import { Booking } from './entity/booking.entity'; -export class BookingRepository extends Repository { +export class BookingRepository { constructor( @InjectRepository(Booking) private readonly bookingRepository: Repository, - ) { - super( - bookingRepository.target, - bookingRepository.manager, - bookingRepository.queryRunner, - ); + ) {} + + save(entity: DeepPartial) { + return this.bookingRepository.save(entity); + } + + delete(entity: Booking) { + return this.bookingRepository.delete(entity); + } + + deleteBooking(userId: number, eventId: number) { + return this.bookingRepository.delete({ + user: Equal(userId), + event: Equal(eventId), + }); + } + + findOneById(userId: number, eventId: number) { + return this.bookingRepository.findOneBy({ + user: Equal(userId), + event: Equal(eventId), + }); + } + findAll() { + return this.bookingRepository.find({ relations: ['user', 'event'] }); } } diff --git a/src/module/booking/booking.service.ts b/src/module/booking/booking.service.ts index 012920a..4d55544 100644 --- a/src/module/booking/booking.service.ts +++ b/src/module/booking/booking.service.ts @@ -3,7 +3,6 @@ import { Injectable, NotFoundException, } from '@nestjs/common'; -import { Equal } from 'typeorm'; import { BookingRepository } from './booking.repository'; import { EventRepository } from '../event/event.repository'; @@ -18,7 +17,7 @@ export class BookingService { async createBooking(user: User, eventId: number) { const event = await this.eventRepository.findOneById(eventId); - const isBookingExists = await this.findOneBooking(user, eventId); + const isBookingExists = await this.findOneBooking(user.id, eventId); if (isBookingExists) { throw new ConflictException(); } @@ -26,22 +25,16 @@ export class BookingService { } async deleteBooking(user: User, eventId: number) { - const result = await this.bookingRepository.delete({ - user: Equal(user.id), - event: Equal(eventId), - }); + const result = await this.bookingRepository.deleteBooking(user.id, eventId); if (result.affected === 0) { throw new NotFoundException(); } } - private findOneBooking(user: User, eventId: number) { - return this.bookingRepository.findOneBy({ - user: Equal(user.id), - event: Equal(eventId), - }); + private findOneBooking(userId: number, eventId: number) { + return this.bookingRepository.findOneById(userId, eventId); } findAll() { - return this.bookingRepository.find({ relations: ['user', 'event'] }); + return this.bookingRepository.findAll(); } } diff --git a/src/module/booking/entity/booking.entity.ts b/src/module/booking/entity/booking.entity.ts index 0184dd0..f665e7c 100644 --- a/src/module/booking/entity/booking.entity.ts +++ b/src/module/booking/entity/booking.entity.ts @@ -1,7 +1,8 @@ -import { Event } from 'src/module/event/entity/event.entity'; -import { User } from 'src/module/user/entity/user.entity'; import { Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; +import { Event } from '../../event/entity/event.entity'; +import { User } from '../../user/entity/user.entity'; + @Entity() export class Booking { @PrimaryGeneratedColumn() diff --git a/src/module/event/dto/create-event.dto.ts b/src/module/event/dto/create-event.dto.ts index 2ae89a7..2aa458d 100644 --- a/src/module/event/dto/create-event.dto.ts +++ b/src/module/event/dto/create-event.dto.ts @@ -5,7 +5,8 @@ import { IsPositive, IsString, } from 'class-validator'; -import { Location } from 'src/config/types/entity.enums'; + +import { Location } from '../../../common/types/entity.enums'; export class CreateEventDto { @IsString() @@ -16,7 +17,8 @@ export class CreateEventDto { @IsDateString() startDate: Date; - description: string; + @IsString() + description?: string; @IsEnum(Location) location: Location; diff --git a/src/module/event/dto/search-event.dto.ts b/src/module/event/dto/search-event.dto.ts index 4d4e97c..8ba1630 100644 --- a/src/module/event/dto/search-event.dto.ts +++ b/src/module/event/dto/search-event.dto.ts @@ -1,19 +1,11 @@ -import { IsEnum, IsNumberString, IsOptional, IsString } from 'class-validator'; -import { Location } from 'src/config/types/entity.enums'; +import { PartialType, PickType } from '@nestjs/swagger'; +import { IsNumberString, IsOptional } from 'class-validator'; -export class SearchEventDto { - @IsOptional() - @IsString() - title?: string; - - @IsOptional() - @IsString() - description?: string; - - @IsOptional() - @IsEnum(Location) - location?: Location; +import { CreateEventDto } from './create-event.dto'; +export class SearchEventDto extends PartialType( + PickType(CreateEventDto, ['title', 'description', 'location', 'tag']), +) { @IsOptional() @IsNumberString() priceFrom?: number; @@ -21,8 +13,4 @@ export class SearchEventDto { @IsOptional() @IsNumberString() priceTo?: number; - - @IsOptional() - @IsString() - tag?: string; } diff --git a/src/module/event/dto/update-event.dto.ts b/src/module/event/dto/update-event.dto.ts new file mode 100644 index 0000000..c26d0b1 --- /dev/null +++ b/src/module/event/dto/update-event.dto.ts @@ -0,0 +1,5 @@ +import { PartialType } from '@nestjs/swagger'; + +import { CreateEventDto } from './create-event.dto'; + +export class UpdateEventDto extends PartialType(CreateEventDto) {} diff --git a/src/module/event/entity/event.entity.ts b/src/module/event/entity/event.entity.ts index aea74fb..742d14c 100644 --- a/src/module/event/entity/event.entity.ts +++ b/src/module/event/entity/event.entity.ts @@ -1,6 +1,3 @@ -import { Location } from 'src/config/types/entity.enums'; -import { Booking } from 'src/module/booking/entity/booking.entity'; -import { User } from 'src/module/user/entity/user.entity'; import { Column, Entity, @@ -9,6 +6,10 @@ import { PrimaryGeneratedColumn, } from 'typeorm'; +import { Location } from '../../../common/types/entity.enums'; +import { Booking } from '../../booking/entity/booking.entity'; +import { User } from '../../user/entity/user.entity'; + @Entity() export class Event { @PrimaryGeneratedColumn() @@ -23,8 +24,11 @@ export class Event { @Column('timestamptz') startDate: Date; - @Column('text') - description: string; + @Column({ + type: 'text', + nullable: true, + }) + description?: string; @Column({ type: 'enum', @@ -39,5 +43,5 @@ export class Event { tag: string; @OneToMany(() => Booking, (booking) => booking.event) - bookings: Booking[]; + bookings?: Booking[]; } diff --git a/src/module/event/event.controller.ts b/src/module/event/event.controller.ts index 2ca4c62..2f2d3b6 100644 --- a/src/module/event/event.controller.ts +++ b/src/module/event/event.controller.ts @@ -6,21 +6,25 @@ import { HttpCode, HttpStatus, Param, + ParseIntPipe, Patch, Post, Query, UseGuards, } from '@nestjs/common'; -import { UserFromRequest } from 'src/config/decorators/user.decorator'; +import { ApiTags } from '@nestjs/swagger'; import { CreateEventDto } from './dto/create-event.dto'; import { SearchEventDto } from './dto/search-event.dto'; +import { UpdateEventDto } from './dto/update-event.dto'; import { EventService } from './event.service'; +import { UserFromRequest } from '../../common/decorators/user.decorator'; import { AccessTokenGuard } from '../auth/guards/access-token.guard'; -import { OrganizerGuard } from '../auth/guards/organizer.guard'; -import { EventOwnerGuard } from '../auth/guards/owner.guard'; import { User } from '../user/entity/user.entity'; +import { OrganizerGuard } from '../user/guards/organizer.guard'; +import { EventOwnerGuard } from '../user/guards/owner.guard'; +@ApiTags('Event') @Controller('event') export class EventController { constructor(private readonly eventService: EventService) {} @@ -40,13 +44,13 @@ export class EventController { } @Get(':id') - read(@Param('id') id: number) { + read(@Param('id', ParseIntPipe) id: number) { return this.eventService.getOneById(id); } @Patch('update/:id') @UseGuards(AccessTokenGuard, EventOwnerGuard) - update(@Param('id') id: number, @Body() updateEventDto: CreateEventDto) { + update(@Param('id') id: number, @Body() updateEventDto: UpdateEventDto) { return this.eventService.updateEvent(id, updateEventDto); } @@ -56,9 +60,4 @@ export class EventController { delete(@Param('id') id: number) { return this.eventService.deleteEvent(id); } - - @Get() - getAll() { - return this.eventService.getAll(); - } } diff --git a/src/module/event/event.repository.ts b/src/module/event/event.repository.ts index 38981de..00b1ab5 100644 --- a/src/module/event/event.repository.ts +++ b/src/module/event/event.repository.ts @@ -1,24 +1,62 @@ import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; +import { + And, + DeepPartial, + Equal, + FindManyOptions, + ILike, + LessThanOrEqual, + MoreThanOrEqual, + Repository, +} from 'typeorm'; +import { SearchEventDto } from './dto/search-event.dto'; import { Event } from './entity/event.entity'; -export class EventRepository extends Repository { +export class EventRepository { constructor( @InjectRepository(Event) private readonly eventRepository: Repository, - ) { - super( - eventRepository.target, - eventRepository.manager, - eventRepository.queryRunner, - ); + ) {} + + create(entity: Partial) { + return this.eventRepository.create(entity); + } + + save(entity: DeepPartial) { + return this.eventRepository.save(entity); + } + + deleteById(id: number) { + return this.eventRepository.delete(id); + } + + find(options: FindManyOptions) { + return this.eventRepository.find(options); } - async findOneById(id: number) { + findOneById(id: number) { return this.eventRepository.findOne({ where: { id }, relations: ['organizer'], }); } + + findEvents(params: SearchEventDto) { + const { title, description, location, tag, priceTo } = params; + const priceFrom = params.priceFrom ?? 0; + + return this.eventRepository.find({ + where: { + title: title ? ILike(`%${title}%`) : null, + description: description ? ILike(`%${description}%`) : null, + location: location ? Equal(location) : null, + tag: tag ? ILike(`%${tag}%`) : null, + price: priceTo + ? And(MoreThanOrEqual(priceFrom), LessThanOrEqual(priceTo)) + : MoreThanOrEqual(priceFrom), + }, + relations: ['organizer'], + }); + } } diff --git a/src/module/event/event.service.ts b/src/module/event/event.service.ts index c057046..9a7571f 100644 --- a/src/module/event/event.service.ts +++ b/src/module/event/event.service.ts @@ -1,18 +1,14 @@ import { Injectable, NotFoundException } from '@nestjs/common'; -import { MailerService } from '@nestjs-modules/mailer'; -import { And, Equal, ILike, LessThanOrEqual, MoreThanOrEqual } from 'typeorm'; import { CreateEventDto } from './dto/create-event.dto'; import { SearchEventDto } from './dto/search-event.dto'; +import { UpdateEventDto } from './dto/update-event.dto'; import { EventRepository } from './event.repository'; import { User } from '../user/entity/user.entity'; @Injectable() export class EventService { - constructor( - private readonly eventRepository: EventRepository, - private readonly mailerService: MailerService, - ) {} + constructor(private readonly eventRepository: EventRepository) {} async createEvent(user: User, createEventDto: CreateEventDto) { const event = this.eventRepository.create(createEventDto); @@ -20,11 +16,8 @@ export class EventService { return await this.eventRepository.save(event); } - async updateEvent(id: number, updateEventDto: CreateEventDto) { + async updateEvent(id: number, updateEventDto: UpdateEventDto) { const event = await this.eventRepository.findOneById(id); - if (!event) { - throw new NotFoundException(); - } const newEvent = { ...updateEventDto, id: event.id, @@ -34,7 +27,7 @@ export class EventService { } async deleteEvent(id: number) { - const result = await this.eventRepository.delete(id); + const result = await this.eventRepository.deleteById(id); if (result.affected === 0) { throw new NotFoundException(); } @@ -43,40 +36,7 @@ export class EventService { return this.eventRepository.findOneById(id); } - getAll() { - return this.eventRepository.find({ relations: ['organizer'] }); - } - getEvents(params: SearchEventDto) { - const { title, description, location, tag, priceTo } = params; - const priceFrom = params.priceFrom ?? 0; - return this.eventRepository.find({ - where: { - title: title ? ILike(`%${title}%`) : null, - description: description ? ILike(`%${description}%`) : null, - location: location ? Equal(location) : null, - tag: tag ? ILike(`%${tag}%`) : null, - price: priceTo - ? And(MoreThanOrEqual(priceFrom), LessThanOrEqual(priceTo)) - : MoreThanOrEqual(priceFrom), - }, - relations: ['organizer'], - }); - } - - sendEmail() { - this.mailerService - .sendMail({ - to: 'test@nestjs.com', - subject: 'Testing Nest MailerModule ✔', - text: 'welcome', - html: 'welcome', - }) - .then(() => { - console.log('success'); - }) - .catch((err) => { - console.log(err); - }); + return this.eventRepository.findEvents(params); } } diff --git a/src/module/mail/mail.module.ts b/src/module/mail/mail.module.ts index 2de0bc0..8d1e122 100644 --- a/src/module/mail/mail.module.ts +++ b/src/module/mail/mail.module.ts @@ -8,15 +8,15 @@ import { MailerModule } from '@nestjs-modules/mailer'; inject: [ConfigService], useFactory: async (configService: ConfigService) => ({ transport: { - host: configService.get('SMTP_HOST'), - port: configService.get('SMTP_PORT'), + host: configService.getOrThrow('SMTP_HOST'), + port: configService.getOrThrow('SMTP_PORT'), auth: { - user: configService.get('SMTP_USER'), - pass: configService.get('SMTP_PASS'), + user: configService.getOrThrow('SMTP_USER'), + pass: configService.getOrThrow('SMTP_PASS'), }, }, defaults: { - from: '"nest-modules" ', + from: configService.getOrThrow('SMTP_FROM'), }, }), }), diff --git a/src/module/scheduler/scheduler.service.ts b/src/module/scheduler/scheduler.service.ts index e2f6eb7..92b2224 100644 --- a/src/module/scheduler/scheduler.service.ts +++ b/src/module/scheduler/scheduler.service.ts @@ -1,4 +1,5 @@ import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; import { Cron, CronExpression } from '@nestjs/schedule'; import { MailerService } from '@nestjs-modules/mailer'; @@ -9,6 +10,7 @@ export class SchedulerService { constructor( private readonly mailerService: MailerService, private readonly userService: UserService, + private readonly congigService: ConfigService, ) {} @Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT) @@ -25,8 +27,8 @@ export class SchedulerService { const sendMailPromises = users.map(({ email }) => { return this.mailerService.sendMail({ to: email, - subject: 'Напоминание', - text: 'У вас назначена встреча сегодня', + subject: this.congigService.getOrThrow('EMAIL_SUBJECT'), + text: this.congigService.getOrThrow('EMAIL_TEXT'), }); }); await Promise.all(sendMailPromises); diff --git a/src/module/user/dto/create-user.dto.ts b/src/module/user/dto/create-user.dto.ts index a7059f3..ed31eda 100644 --- a/src/module/user/dto/create-user.dto.ts +++ b/src/module/user/dto/create-user.dto.ts @@ -1,3 +1,4 @@ +import { ApiProperty } from '@nestjs/swagger'; import { IsEmail, IsEnum, @@ -5,11 +6,10 @@ import { IsString, IsStrongPassword, } from 'class-validator'; -import { Location, UserRole } from 'src/config/types/entity.enums'; -export class CreateUserDto { - id: number; +import { Location, UserRole } from '../../../common/types/entity.enums'; +export class CreateUserDto { @IsEmail() email: string; @@ -22,7 +22,8 @@ export class CreateUserDto { @IsString() fullname: string; + @ApiProperty({ default: UserRole.USER }) @IsOptional() @IsEnum(UserRole) - role: UserRole; + role?: UserRole; } diff --git a/src/module/user/dto/update-user.dto.ts b/src/module/user/dto/update-user.dto.ts index 22da112..92d12c0 100644 --- a/src/module/user/dto/update-user.dto.ts +++ b/src/module/user/dto/update-user.dto.ts @@ -1,12 +1,8 @@ -import { IsEnum, IsOptional, IsString } from 'class-validator'; -import { Location } from 'src/config/types/entity.enums'; +import { PartialType, PickType } from '@nestjs/swagger'; -export class UpdateUserDto { - @IsEnum(Location) - @IsOptional() - location: Location; +import { CreateUserDto } from './create-user.dto'; - @IsString() - @IsOptional() - fullname: string; -} +export class UpdateUserDto extends PickType(PartialType(CreateUserDto), [ + 'location', + 'fullname', +]) {} diff --git a/src/module/user/entity/user.entity.ts b/src/module/user/entity/user.entity.ts index 0009405..cdbf802 100644 --- a/src/module/user/entity/user.entity.ts +++ b/src/module/user/entity/user.entity.ts @@ -1,9 +1,10 @@ import { Exclude } from 'class-transformer'; -import { UserRole, Location } from 'src/config/types/entity.enums'; -import { Booking } from 'src/module/booking/entity/booking.entity'; -import { Event } from 'src/module/event/entity/event.entity'; import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm'; +import { UserRole, Location } from '../../../common/types/entity.enums'; +import { Booking } from '../../booking/entity/booking.entity'; +import { Event } from '../../event/entity/event.entity'; + @Entity() export class User { @PrimaryGeneratedColumn() @@ -21,13 +22,10 @@ export class User { @Column({ type: 'enum', enum: Location, - nullable: true, }) location: Location; - @Column({ - nullable: true, - }) + @Column() fullname: string; @Column({ @@ -38,8 +36,8 @@ export class User { role: UserRole; @OneToMany(() => Event, (event) => event.organizer) - events: Event[]; + events?: Event[]; @OneToMany(() => Booking, (booking) => booking.user) - bookings: Booking[]; + bookings?: Booking[]; } diff --git a/src/module/auth/guards/organizer.guard.ts b/src/module/user/guards/organizer.guard.ts similarity index 84% rename from src/module/auth/guards/organizer.guard.ts rename to src/module/user/guards/organizer.guard.ts index 93ef055..5900ae4 100644 --- a/src/module/auth/guards/organizer.guard.ts +++ b/src/module/user/guards/organizer.guard.ts @@ -1,6 +1,6 @@ import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; -import { UserRole } from 'src/config/types/entity.enums'; +import { UserRole } from '../../../common/types/entity.enums'; @Injectable() export class OrganizerGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { diff --git a/src/module/auth/guards/owner.guard.ts b/src/module/user/guards/owner.guard.ts similarity index 59% rename from src/module/auth/guards/owner.guard.ts rename to src/module/user/guards/owner.guard.ts index 41ce94e..c9dc77e 100644 --- a/src/module/auth/guards/owner.guard.ts +++ b/src/module/user/guards/owner.guard.ts @@ -1,5 +1,7 @@ import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; -import { EventRepository } from 'src/module/event/event.repository'; + +import { parseId } from '../../../common/utils/parse-id'; +import { EventRepository } from '../../event/event.repository'; @Injectable() export class EventOwnerGuard implements CanActivate { @@ -8,8 +10,9 @@ export class EventOwnerGuard implements CanActivate { const request = context.switchToHttp().getRequest(); const user = request.user; const id = request.params.id; - const event = await this.eventRepository.findOneById(id); + const parsedId = parseId(id); + const event = await this.eventRepository.findOneById(parsedId); - return event.organizer.id === user.id; + return event?.organizer.id === user.id; } } diff --git a/src/module/user/user.controller.ts b/src/module/user/user.controller.ts index a5c6223..b9726a7 100644 --- a/src/module/user/user.controller.ts +++ b/src/module/user/user.controller.ts @@ -1,11 +1,13 @@ import { Body, Get, Patch, UseGuards, Controller } from '@nestjs/common'; -import { UserFromRequest } from 'src/config/decorators/user.decorator'; +import { ApiTags } from '@nestjs/swagger'; import { UpdateUserDto } from './dto/update-user.dto'; import { User } from './entity/user.entity'; import { UserService } from './user.service'; +import { UserFromRequest } from '../../common/decorators/user.decorator'; import { AccessTokenGuard } from '../auth/guards/access-token.guard'; +@ApiTags('User') @Controller('user') export class UserController { constructor(private readonly userService: UserService) {} diff --git a/src/module/user/user.module.ts b/src/module/user/user.module.ts index 559a7f6..643aa61 100644 --- a/src/module/user/user.module.ts +++ b/src/module/user/user.module.ts @@ -1,9 +1,9 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { UserRepository } from 'src/module/user/user.repository'; import { User } from './entity/user.entity'; import { UserController } from './user.controller'; +import { UserRepository } from './user.repository'; import { UserService } from './user.service'; @Module({ diff --git a/src/module/user/user.repository.ts b/src/module/user/user.repository.ts index dee5742..ca84e5f 100644 --- a/src/module/user/user.repository.ts +++ b/src/module/user/user.repository.ts @@ -1,17 +1,20 @@ import { InjectRepository } from '@nestjs/typeorm'; -import { User } from 'src/module/user/entity/user.entity'; import { Between, Repository } from 'typeorm'; -export class UserRepository extends Repository { +import { User } from './entity/user.entity'; + +export class UserRepository { constructor( @InjectRepository(User) private readonly userRepository: Repository, - ) { - super( - userRepository.target, - userRepository.manager, - userRepository.queryRunner, - ); + ) {} + + find() { + return this.userRepository.find({ relations: ['events'] }); + } + + save(entity: Partial) { + return this.userRepository.save(entity); } findOneByEmail(email: string) { diff --git a/src/module/user/user.service.ts b/src/module/user/user.service.ts index b052fcd..198c3e4 100644 --- a/src/module/user/user.service.ts +++ b/src/module/user/user.service.ts @@ -1,9 +1,9 @@ import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { hash } from 'argon2'; -import { UserRepository } from 'src/module/user/user.repository'; import { CreateUserDto } from './dto/create-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; +import { UserRepository } from './user.repository'; @Injectable() export class UserService { @@ -18,6 +18,7 @@ export class UserService { const hashedPassword = await hash(user.password); user.password = hashedPassword; user.email = email; + return this.userRepository.save(user); } @@ -28,12 +29,11 @@ export class UserService { fullname: updateUserDto.fullname, location: updateUserDto.location, }; - return this.userRepository.save(updatedUser); } getAll() { - return this.userRepository.find({ relations: ['events'] }); + return this.userRepository.find(); } getUsersWithAppointments(today: Date, tomorrow: Date) { diff --git a/tsconfig.json b/tsconfig.json index 95f5641..3b92ed7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,6 +16,6 @@ "noImplicitAny": false, "strictBindCallApply": false, "forceConsistentCasingInFileNames": false, - "noFallthroughCasesInSwitch": false + "noFallthroughCasesInSwitch": false, } }