From 5294cd35d23fbe020b467a8bed45e8210f88829e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 7 Nov 2023 14:37:41 +0900 Subject: [PATCH 001/185] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EC=B4=88=EA=B8=B0=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/.eslintrc.js | 31 + back/.gitignore | 37 + back/.prettierrc | 10 + back/nest-cli.json | 8 + back/package-lock.json | 15482 ++++++++++++++++++++++++++++++ back/package.json | 73 + back/src/app.controller.spec.ts | 22 + back/src/app.controller.ts | 12 + back/src/app.module.ts | 10 + back/src/app.service.ts | 8 + back/src/main.ts | 10 + back/test/app.e2e-spec.ts | 24 + back/test/jest-e2e.json | 9 + back/tsconfig.build.json | 4 + back/tsconfig.json | 21 + 15 files changed, 15761 insertions(+) create mode 100644 back/.eslintrc.js create mode 100644 back/.gitignore create mode 100644 back/.prettierrc create mode 100644 back/nest-cli.json create mode 100644 back/package-lock.json create mode 100644 back/package.json create mode 100644 back/src/app.controller.spec.ts create mode 100644 back/src/app.controller.ts create mode 100644 back/src/app.module.ts create mode 100644 back/src/app.service.ts create mode 100644 back/src/main.ts create mode 100644 back/test/app.e2e-spec.ts create mode 100644 back/test/jest-e2e.json create mode 100644 back/tsconfig.build.json create mode 100644 back/tsconfig.json diff --git a/back/.eslintrc.js b/back/.eslintrc.js new file mode 100644 index 0000000..356232f --- /dev/null +++ b/back/.eslintrc.js @@ -0,0 +1,31 @@ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + tsconfigRootDir: __dirname, + sourceType: 'module', + }, + plugins: ['@typescript-eslint/eslint-plugin'], + extends: [ + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + root: true, + env: { + node: true, + jest: true, + }, + ignorePatterns: ['.eslintrc.js'], + rules: { + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-explicit-any': 'off', + 'prettier/prettier': [ + 'error', + { + endOfLine: 'auto', + }, + ], + }, +}; diff --git a/back/.gitignore b/back/.gitignore new file mode 100644 index 0000000..ea48d65 --- /dev/null +++ b/back/.gitignore @@ -0,0 +1,37 @@ +# compiled output +/dist +/node_modules + +# Logs +logs +*.log +npm-debug.log* +pnpm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# OS +.DS_Store + +# Tests +/coverage +/.nyc_output + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +.env \ No newline at end of file diff --git a/back/.prettierrc b/back/.prettierrc new file mode 100644 index 0000000..d0cffe5 --- /dev/null +++ b/back/.prettierrc @@ -0,0 +1,10 @@ +{ + "singleQuote": true, + "semi": true, + "useTabs": false, + "tabWidth": 2, + "bracketSpacing": true, + "trailingComma": "none", + "arrowParens": "avoid", + "endOfLine": "auto" +} diff --git a/back/nest-cli.json b/back/nest-cli.json new file mode 100644 index 0000000..f9aa683 --- /dev/null +++ b/back/nest-cli.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/nest-cli", + "collection": "@nestjs/schematics", + "sourceRoot": "src", + "compilerOptions": { + "deleteOutDir": true + } +} diff --git a/back/package-lock.json b/back/package-lock.json new file mode 100644 index 0000000..e2fd0ea --- /dev/null +++ b/back/package-lock.json @@ -0,0 +1,15482 @@ +{ + "name": "ssock", + "version": "0.0.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "ssock", + "version": "0.0.1", + "license": "UNLICENSED", + "dependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/passport": "^10.0.2", + "@nestjs/platform-express": "^10.0.0", + "dotenv": "^16.3.1", + "passport": "^0.6.0", + "passport-google-oauth20": "^2.0.0", + "reflect-metadata": "^0.1.13", + "rxjs": "^7.8.1" + }, + "devDependencies": { + "@nestjs/cli": "^10.0.0", + "@nestjs/schematics": "^10.0.0", + "@nestjs/testing": "^10.0.0", + "@types/express": "^4.17.17", + "@types/jest": "^29.5.2", + "@types/node": "^20.3.1", + "@types/supertest": "^2.0.12", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "eslint": "^8.42.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "jest": "^29.5.0", + "prettier": "^3.0.0", + "source-map-support": "^0.5.21", + "supertest": "^6.3.3", + "ts-jest": "^29.1.0", + "ts-loader": "^9.4.3", + "ts-node": "^10.9.1", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.1.3" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@angular-devkit/core": { + "version": "16.2.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.8.tgz", + "integrity": "sha512-PTGozYvh1Bin5lB15PwcXa26Ayd17bWGLS3H8Rs0s+04mUDvfNofmweaX1LgumWWy3nCUTDuwHxX10M3G0wE2g==", + "dev": true, + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "picomatch": "2.3.1", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/schematics": { + "version": "16.2.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.8.tgz", + "integrity": "sha512-MBiKZOlR9/YMdflALr7/7w/BGAfo/BGTrlkqsIB6rDWV1dYiCgxI+033HsiNssLS6RQyCFx/e7JA2aBBzu9zEg==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "16.2.8", + "jsonc-parser": "3.2.0", + "magic-string": "0.30.1", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics-cli": { + "version": "16.2.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-16.2.8.tgz", + "integrity": "sha512-EXURJCzWTVYCipiTT4vxQQOrF63asOUDbeOy3OtiSh7EwIUvxm3BPG6hquJqngEnI/N6bA75NJ1fBhU6Hrh7eA==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "16.2.8", + "@angular-devkit/schematics": "16.2.8", + "ansi-colors": "4.1.3", + "inquirer": "8.2.4", + "symbol-observable": "4.0.0", + "yargs-parser": "21.1.1" + }, + "bin": { + "schematics": "bin/schematics.js" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/inquirer": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", + "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", + "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", + "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.2", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", + "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "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", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.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", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "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-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@eslint/js": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", + "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@lukeed/csprng": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", + "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@nestjs/cli": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.2.1.tgz", + "integrity": "sha512-CAJAQwmxFZfB3RTvqz/eaXXWpyU+mZ4QSqfBYzjneTsPgF+uyOAW3yQpaLNn9Dfcv39R9UxSuAhayv6yuFd+Jg==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "16.2.8", + "@angular-devkit/schematics": "16.2.8", + "@angular-devkit/schematics-cli": "16.2.8", + "@nestjs/schematics": "^10.0.1", + "chalk": "4.1.2", + "chokidar": "3.5.3", + "cli-table3": "0.6.3", + "commander": "4.1.1", + "fork-ts-checker-webpack-plugin": "9.0.2", + "glob": "10.3.10", + "inquirer": "8.2.6", + "node-emoji": "1.11.0", + "ora": "5.4.1", + "os-name": "4.0.1", + "rimraf": "4.4.1", + "shelljs": "0.8.5", + "source-map-support": "0.5.21", + "tree-kill": "1.2.2", + "tsconfig-paths": "4.2.0", + "tsconfig-paths-webpack-plugin": "4.1.0", + "typescript": "5.2.2", + "webpack": "5.89.0", + "webpack-node-externals": "3.0.0" + }, + "bin": { + "nest": "bin/nest.js" + }, + "engines": { + "node": ">= 16.14" + }, + "peerDependencies": { + "@swc/cli": "^0.1.62", + "@swc/core": "^1.3.62" + }, + "peerDependenciesMeta": { + "@swc/cli": { + "optional": true + }, + "@swc/core": { + "optional": true + } + } + }, + "node_modules/@nestjs/common": { + "version": "10.2.8", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.2.8.tgz", + "integrity": "sha512-rmpwcdvq2IWMmsUVP8rsdKub6uDWk7dwCYo0aif50JTwcvcxzaP3iKVFKoSgvp0RKYu8h15+/AEOfaInmPpl0Q==", + "dependencies": { + "iterare": "1.2.1", + "tslib": "2.6.2", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "node_modules/@nestjs/core": { + "version": "10.2.8", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.2.8.tgz", + "integrity": "sha512-9+MZ2s8ixfY9Bl/M9ofChiyYymcwdK9ZWNH4GDMF7Am7XRAQ1oqde6MYGG05rhQwiVXuTwaYLlXciJKfsrg5qg==", + "hasInstallScript": true, + "dependencies": { + "@nuxtjs/opencollective": "0.3.2", + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "3.2.0", + "tslib": "2.6.2", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "@nestjs/websockets": "^10.0.0", + "reflect-metadata": "^0.1.12", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + }, + "@nestjs/websockets": { + "optional": true + } + } + }, + "node_modules/@nestjs/passport": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-10.0.2.tgz", + "integrity": "sha512-od31vfB2z3y05IDB5dWSbCGE2+pAf2k2WCBinNuTTOxN0O0+wtO1L3kawj/aCW3YR9uxsTOVbTDwtwgpNNsnjQ==", + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "passport": "^0.4.0 || ^0.5.0 || ^0.6.0" + } + }, + "node_modules/@nestjs/platform-express": { + "version": "10.2.8", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.2.8.tgz", + "integrity": "sha512-WoSSVtwIRc5AdGMHWVzWZK4JZLT0f4o2xW8P9gQvcX+omL8W1kXCfY8GQYXNBG84XmBNYH8r0FtC8oMe/lH5NQ==", + "dependencies": { + "body-parser": "1.20.2", + "cors": "2.8.5", + "express": "4.18.2", + "multer": "1.4.4-lts.1", + "tslib": "2.6.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0" + } + }, + "node_modules/@nestjs/schematics": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-10.0.3.tgz", + "integrity": "sha512-2BRujK0GqGQ7j1Zpz+obVfskDnnOeVKt5aXoSaVngKo8Oczy8uYCY+R547TQB+Kf35epdfFER2pVnQrX3/It5A==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "16.2.8", + "@angular-devkit/schematics": "16.2.8", + "comment-json": "4.2.3", + "jsonc-parser": "3.2.0", + "pluralize": "8.0.0" + }, + "peerDependencies": { + "typescript": ">=4.8.2" + } + }, + "node_modules/@nestjs/testing": { + "version": "10.2.8", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.2.8.tgz", + "integrity": "sha512-9Kj5IQhM67/nj/MT6Wi2OmWr5YQnCMptwKVFrX1TDaikpY12196v7frk0jVjdT7wms7rV07GZle9I2z0aSjqtQ==", + "dev": true, + "dependencies": { + "tslib": "2.6.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + } + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nuxtjs/opencollective": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", + "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", + "dependencies": { + "chalk": "^4.1.0", + "consola": "^2.15.0", + "node-fetch": "^2.6.1" + }, + "bin": { + "opencollective": "bin/opencollective.js" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/utils": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", + "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "fast-glob": "^3.3.0", + "is-glob": "^4.0.3", + "open": "^9.1.0", + "picocolors": "^1.0.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.3.tgz", + "integrity": "sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.6", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.6.tgz", + "integrity": "sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.3.tgz", + "integrity": "sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.3.tgz", + "integrity": "sha512-Lsh766rGEFbaxMIDH7Qa+Yha8cMVI3qAK6CHt3OR0YfxOIn5Z54iHiyDRycHrBqeIiqGa20Kpsv1cavfBKkRSw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.4", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.4.tgz", + "integrity": "sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.37", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz", + "integrity": "sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookiejar": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.3.tgz", + "integrity": "sha512-LZ8SD3LpNmLMDLkG2oCBjZg+ETnx6XdCjydUE0HwojDmnDfDUnhMKKbtth1TZh+hzcqb03azrYWoXLS8sMXdqg==", + "dev": true + }, + "node_modules/@types/eslint": { + "version": "8.44.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.6.tgz", + "integrity": "sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.6.tgz", + "integrity": "sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.4.tgz", + "integrity": "sha512-2JwWnHK9H+wUZNorf2Zr6ves96WHoWDJIftkcxPKsS7Djta6Zu519LarhRNljPXkpsZR2ZMwNCPeW7omW07BJw==", + "dev": true + }, + "node_modules/@types/express": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.20.tgz", + "integrity": "sha512-rOaqlkgEvOW495xErXMsmyX3WKBInbhG5eqojXYi3cGUaLoRDlXa5d52fkfWZT963AZ3v2eZ4MbKE6WpDAGVsw==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.39", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.39.tgz", + "integrity": "sha512-BiEUfAiGCOllomsRAZOiMFP7LAnrifHpt56pc4Z7l9K6ACyN06Ns1JLMBxwkfLOjJRlSf06NwWsT7yzfpaVpyQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.8.tgz", + "integrity": "sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.3.tgz", + "integrity": "sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA==", + "dev": true + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-zONci81DZYCZjiLe0r6equvZut0b+dBRPBN5kBDjsONnutYNtJMoWQ9uR2RkL1gLG9NMTzvf+29e5RFfPbeKhQ==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.2.tgz", + "integrity": "sha512-8toY6FgdltSdONav1XtUHl4LN1yTmLza+EuDazb/fEmRNCwjyqNVIQWs2IfC74IqjHkREs/nQ2FWq5kZU9IC0w==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.3.tgz", + "integrity": "sha512-1nESsePMBlf0RPRffLZi5ujYh7IH1BWL4y9pr+Bn3cJBdxz+RTP8bUFljLz9HvzhhOSWKdyBZ4DIivdL6rvgZg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.7", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.7.tgz", + "integrity": "sha512-HLyetab6KVPSiF+7pFcUyMeLsx25LDNDemw9mGsJBkai/oouwrjTycocSDYopMEwFhN2Y4s9oPyOCZNofgSt2g==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.4.tgz", + "integrity": "sha512-1Gjee59G25MrQGk8bsNvC6fxNiRgUlGn2wlhGf95a59DrprnnHk80FIMMFG9XHMdrfsuA119ht06QPDXA1Z7tw==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.8.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", + "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/qs": { + "version": "6.9.9", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", + "integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz", + "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.3.tgz", + "integrity": "sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.4.tgz", + "integrity": "sha512-aqqNfs1XTF0HDrFdlY//+SGUxmdSUbjeRXb5iaZc3x0/vMbYmdw9qvOgHWOyyLFxSSRnUuP5+724zBgfw8/WAw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.2.tgz", + "integrity": "sha512-g7CK9nHdwjK2n0ymT2CW698FuWJRIx+RP6embAzZ2Qi8/ilIrA1Imt2LVSeHUzKvpoi7BhmmQcXz95eS0f2JXw==", + "dev": true + }, + "node_modules/@types/superagent": { + "version": "4.1.20", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.20.tgz", + "integrity": "sha512-GfpwJgYSr3yO+nArFkmyqv3i0vZavyEG5xPd/o95RwpKYpsOKJYI5XLdxLpdRbZI3YiGKKdIOFIf/jlP7A0Jxg==", + "dev": true, + "dependencies": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "node_modules/@types/supertest": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.15.tgz", + "integrity": "sha512-jUCZZ/TMcpGzoSaed9Gjr8HCf3HehExdibyw3OHHEL1als1KmyzcOZZH4MjbObI8TkWsEr7bc7gsW0WTDni+qQ==", + "dev": true, + "dependencies": { + "@types/superagent": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.29", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.29.tgz", + "integrity": "sha512-nacjqA3ee9zRF/++a3FUY1suHTFKZeHba2n8WeDw9cCVdmzmHpIxyzOJBcpHvvEmS8E9KqWlSnWHUkOrkhWcvA==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.2", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.2.tgz", + "integrity": "sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.1.tgz", + "integrity": "sha512-w0tiiRc9I4S5XSXXrMHOWgHgxbrBn1Ro+PmiYhSg2ZVdxrAJtQgzU5o2m1BfP6UOn7Vxcc6152vFjQfmZR4xEg==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/type-utils": "6.9.1", + "@typescript-eslint/utils": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.1.tgz", + "integrity": "sha512-C7AK2wn43GSaCUZ9do6Ksgi2g3mwFkMO3Cis96kzmgudoVaKyt62yNzJOktP0HDLb/iO2O0n2lBOzJgr6Q/cyg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", + "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.1.tgz", + "integrity": "sha512-eh2oHaUKCK58qIeYp19F5V5TbpM52680sB4zNSz29VBQPTWIlE/hCj5P5B1AChxECe/fmZlspAWFuRniep1Skg==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/utils": "6.9.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", + "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", + "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.1.tgz", + "integrity": "sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/typescript-estree": "6.9.1", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", + "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.9.1", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "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 + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/array-timsort": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", + "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "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-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@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" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "dev": true, + "dependencies": { + "big-integer": "^1.6.44" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dev": true, + "dependencies": { + "run-applescript": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dependencies": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001559", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001559.tgz", + "integrity": "sha512-cPiMKZgqgkg5LY3/ntGeLFUpi6tzddBNS58A4tnTgQw1zON7u2sZMU7SzOeVH4tj20++9ggL+V6FDOFMTaFFYA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", + "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", + "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/comment-json": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.3.tgz", + "integrity": "sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw==", + "dev": true, + "dependencies": { + "array-timsort": "^1.0.3", + "core-util-is": "^1.0.3", + "esprima": "^4.0.1", + "has-own-prop": "^2.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", + "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", + "dev": true, + "dependencies": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^7.1.1", + "titleize": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "dev": true, + "dependencies": { + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/default-browser/node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/default-browser/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/default-browser/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.575", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.575.tgz", + "integrity": "sha512-kY2BGyvgAHiX899oF6xLXSIf99bAvvdPhDoJwG77nxCSyWYuRH6e9a9a3gpXBvCs6lj4dQZJkfnW2hdKWHEISg==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-module-lexer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", + "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", + "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.52.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", + "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz", + "integrity": "sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.5" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/express/node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", + "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/flat-cache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", + "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^8.2.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">=12.13.0", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formidable": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", + "integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==", + "dev": true, + "dependencies": { + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0", + "qs": "^6.11.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", + "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "dependencies": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-own-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", + "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/inquirer": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-wsl/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", + "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/iterare": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", + "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/macos-release": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.1.tgz", + "integrity": "sha512-DXqXhEM7gW59OjZO8NIjBCz9AQ1BEMrfiOAl4AYByHCtVHRF4KoGNO8mqQeM8lRCtQe/UnJ4imO/d2HdkKsd+A==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/magic-string": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.1.tgz", + "integrity": "sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "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==", + "dev": true + }, + "node_modules/multer": { + "version": "1.4.4-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz", + "integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true + }, + "node_modules/node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", + "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", + "dev": true, + "dependencies": { + "default-browser": "^4.0.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/os-name": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-4.0.1.tgz", + "integrity": "sha512-xl9MAoU97MH1Xt5K9ERft2YfCAoaO6msy1OBA0ozxEC0x0TmIoE6K3QvgJMMZA9yKGLmHXNY/YZoDbiGDj4zYw==", + "dev": true, + "dependencies": { + "macos-release": "^2.5.0", + "windows-release": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/passport": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", + "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-google-oauth20": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", + "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==", + "dependencies": { + "passport-oauth2": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/passport-oauth2": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.7.0.tgz", + "integrity": "sha512-j2gf34szdTF2Onw3+76alNnaAExlUmHvkc7cL+cmaS5NzHzDP/BvFHJruueQ9XAeNOdpI+CH+PWid8RA7KCwAQ==", + "dependencies": { + "base64url": "3.x.x", + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", + "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/path-to-regexp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", + "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", + "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dev": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", + "integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==", + "dev": true, + "dependencies": { + "glob": "^9.2.0" + }, + "bin": { + "rimraf": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/schema-utils/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/schema-utils/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "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.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dev": true, + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/shelljs/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/superagent": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", + "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==", + "dev": true, + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^2.1.2", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=6.4.0 <13 || >=14" + } + }, + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/supertest": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.3.tgz", + "integrity": "sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA==", + "dev": true, + "dependencies": { + "methods": "^1.1.2", + "superagent": "^8.0.5" + }, + "engines": { + "node": ">=6.4.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/synckit": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", + "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", + "dev": true, + "dependencies": { + "@pkgr/utils": "^2.3.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", + "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.17", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/titleize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", + "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-jest": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "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" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-loader": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.0.tgz", + "integrity": "sha512-LLlB/pkB4q9mW2yLdFMnK3dEHbrBjeZTYguaaIfusyojBgAGf5kF+O6KcWqiGzWqHk0LBsoolrp4VftEURhybg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tsconfig-paths-webpack-plugin": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.1.0.tgz", + "integrity": "sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.7.0", + "tsconfig-paths": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uid": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", + "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", + "dependencies": { + "@lukeed/csprng": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, + "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==", + "dev": true + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", + "integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/webpack": { + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-node-externals": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", + "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/windows-release": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-4.0.0.tgz", + "integrity": "sha512-OxmV4wzDKB1x7AZaZgXMVsdJ1qER1ed83ZrTYd5Bwq2HfJVg3DJS8nqlAG4sMoJ7mu8cuRmLEYyU13BKwctRAg==", + "dev": true, + "dependencies": { + "execa": "^4.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/windows-release/node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/windows-release/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/windows-release/node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true, + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/windows-release/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@angular-devkit/core": { + "version": "16.2.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.8.tgz", + "integrity": "sha512-PTGozYvh1Bin5lB15PwcXa26Ayd17bWGLS3H8Rs0s+04mUDvfNofmweaX1LgumWWy3nCUTDuwHxX10M3G0wE2g==", + "dev": true, + "requires": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "picomatch": "2.3.1", + "rxjs": "7.8.1", + "source-map": "0.7.4" + } + }, + "@angular-devkit/schematics": { + "version": "16.2.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.8.tgz", + "integrity": "sha512-MBiKZOlR9/YMdflALr7/7w/BGAfo/BGTrlkqsIB6rDWV1dYiCgxI+033HsiNssLS6RQyCFx/e7JA2aBBzu9zEg==", + "dev": true, + "requires": { + "@angular-devkit/core": "16.2.8", + "jsonc-parser": "3.2.0", + "magic-string": "0.30.1", + "ora": "5.4.1", + "rxjs": "7.8.1" + } + }, + "@angular-devkit/schematics-cli": { + "version": "16.2.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-16.2.8.tgz", + "integrity": "sha512-EXURJCzWTVYCipiTT4vxQQOrF63asOUDbeOy3OtiSh7EwIUvxm3BPG6hquJqngEnI/N6bA75NJ1fBhU6Hrh7eA==", + "dev": true, + "requires": { + "@angular-devkit/core": "16.2.8", + "@angular-devkit/schematics": "16.2.8", + "ansi-colors": "4.1.3", + "inquirer": "8.2.4", + "symbol-observable": "4.0.0", + "yargs-parser": "21.1.1" + }, + "dependencies": { + "inquirer": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", + "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "requires": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/compat-data": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", + "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", + "dev": true + }, + "@babel/core": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", + "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.2", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "requires": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.15" + } + }, + "@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true + }, + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "dev": true + }, + "@babel/helpers": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", + "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0" + } + }, + "@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "dev": true + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + } + }, + "@babel/traverse": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "optional": true + }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + } + } + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + } + } + }, + "@eslint/js": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", + "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", + "dev": true + }, + "@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + } + }, + "@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "requires": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + } + }, + "@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "requires": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + } + }, + "@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "requires": { + "jest-get-type": "^29.6.3" + } + }, + "@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + } + }, + "@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "requires": { + "@sinclair/typebox": "^0.27.8" + } + }, + "@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + } + }, + "@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "requires": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + } + }, + "@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + } + }, + "@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@lukeed/csprng": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", + "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==" + }, + "@nestjs/cli": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.2.1.tgz", + "integrity": "sha512-CAJAQwmxFZfB3RTvqz/eaXXWpyU+mZ4QSqfBYzjneTsPgF+uyOAW3yQpaLNn9Dfcv39R9UxSuAhayv6yuFd+Jg==", + "dev": true, + "requires": { + "@angular-devkit/core": "16.2.8", + "@angular-devkit/schematics": "16.2.8", + "@angular-devkit/schematics-cli": "16.2.8", + "@nestjs/schematics": "^10.0.1", + "chalk": "4.1.2", + "chokidar": "3.5.3", + "cli-table3": "0.6.3", + "commander": "4.1.1", + "fork-ts-checker-webpack-plugin": "9.0.2", + "glob": "10.3.10", + "inquirer": "8.2.6", + "node-emoji": "1.11.0", + "ora": "5.4.1", + "os-name": "4.0.1", + "rimraf": "4.4.1", + "shelljs": "0.8.5", + "source-map-support": "0.5.21", + "tree-kill": "1.2.2", + "tsconfig-paths": "4.2.0", + "tsconfig-paths-webpack-plugin": "4.1.0", + "typescript": "5.2.2", + "webpack": "5.89.0", + "webpack-node-externals": "3.0.0" + } + }, + "@nestjs/common": { + "version": "10.2.8", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.2.8.tgz", + "integrity": "sha512-rmpwcdvq2IWMmsUVP8rsdKub6uDWk7dwCYo0aif50JTwcvcxzaP3iKVFKoSgvp0RKYu8h15+/AEOfaInmPpl0Q==", + "requires": { + "iterare": "1.2.1", + "tslib": "2.6.2", + "uid": "2.0.2" + } + }, + "@nestjs/core": { + "version": "10.2.8", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.2.8.tgz", + "integrity": "sha512-9+MZ2s8ixfY9Bl/M9ofChiyYymcwdK9ZWNH4GDMF7Am7XRAQ1oqde6MYGG05rhQwiVXuTwaYLlXciJKfsrg5qg==", + "requires": { + "@nuxtjs/opencollective": "0.3.2", + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "3.2.0", + "tslib": "2.6.2", + "uid": "2.0.2" + } + }, + "@nestjs/passport": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-10.0.2.tgz", + "integrity": "sha512-od31vfB2z3y05IDB5dWSbCGE2+pAf2k2WCBinNuTTOxN0O0+wtO1L3kawj/aCW3YR9uxsTOVbTDwtwgpNNsnjQ==", + "requires": {} + }, + "@nestjs/platform-express": { + "version": "10.2.8", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.2.8.tgz", + "integrity": "sha512-WoSSVtwIRc5AdGMHWVzWZK4JZLT0f4o2xW8P9gQvcX+omL8W1kXCfY8GQYXNBG84XmBNYH8r0FtC8oMe/lH5NQ==", + "requires": { + "body-parser": "1.20.2", + "cors": "2.8.5", + "express": "4.18.2", + "multer": "1.4.4-lts.1", + "tslib": "2.6.2" + } + }, + "@nestjs/schematics": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-10.0.3.tgz", + "integrity": "sha512-2BRujK0GqGQ7j1Zpz+obVfskDnnOeVKt5aXoSaVngKo8Oczy8uYCY+R547TQB+Kf35epdfFER2pVnQrX3/It5A==", + "dev": true, + "requires": { + "@angular-devkit/core": "16.2.8", + "@angular-devkit/schematics": "16.2.8", + "comment-json": "4.2.3", + "jsonc-parser": "3.2.0", + "pluralize": "8.0.0" + } + }, + "@nestjs/testing": { + "version": "10.2.8", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.2.8.tgz", + "integrity": "sha512-9Kj5IQhM67/nj/MT6Wi2OmWr5YQnCMptwKVFrX1TDaikpY12196v7frk0jVjdT7wms7rV07GZle9I2z0aSjqtQ==", + "dev": true, + "requires": { + "tslib": "2.6.2" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@nuxtjs/opencollective": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", + "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", + "requires": { + "chalk": "^4.1.0", + "consola": "^2.15.0", + "node-fetch": "^2.6.1" + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true + }, + "@pkgr/utils": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", + "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "fast-glob": "^3.3.0", + "is-glob": "^4.0.3", + "open": "^9.1.0", + "picocolors": "^1.0.0", + "tslib": "^2.6.0" + } + }, + "@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^3.0.0" + } + }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "@types/babel__core": { + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.3.tgz", + "integrity": "sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.6", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.6.tgz", + "integrity": "sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.3.tgz", + "integrity": "sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.3.tgz", + "integrity": "sha512-Lsh766rGEFbaxMIDH7Qa+Yha8cMVI3qAK6CHt3OR0YfxOIn5Z54iHiyDRycHrBqeIiqGa20Kpsv1cavfBKkRSw==", + "dev": true, + "requires": { + "@babel/types": "^7.20.7" + } + }, + "@types/body-parser": { + "version": "1.19.4", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.4.tgz", + "integrity": "sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.37", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz", + "integrity": "sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/cookiejar": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.3.tgz", + "integrity": "sha512-LZ8SD3LpNmLMDLkG2oCBjZg+ETnx6XdCjydUE0HwojDmnDfDUnhMKKbtth1TZh+hzcqb03azrYWoXLS8sMXdqg==", + "dev": true + }, + "@types/eslint": { + "version": "8.44.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.6.tgz", + "integrity": "sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.6.tgz", + "integrity": "sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==", + "dev": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.4.tgz", + "integrity": "sha512-2JwWnHK9H+wUZNorf2Zr6ves96WHoWDJIftkcxPKsS7Djta6Zu519LarhRNljPXkpsZR2ZMwNCPeW7omW07BJw==", + "dev": true + }, + "@types/express": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.20.tgz", + "integrity": "sha512-rOaqlkgEvOW495xErXMsmyX3WKBInbhG5eqojXYi3cGUaLoRDlXa5d52fkfWZT963AZ3v2eZ4MbKE6WpDAGVsw==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.39", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.39.tgz", + "integrity": "sha512-BiEUfAiGCOllomsRAZOiMFP7LAnrifHpt56pc4Z7l9K6ACyN06Ns1JLMBxwkfLOjJRlSf06NwWsT7yzfpaVpyQ==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "@types/graceful-fs": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.8.tgz", + "integrity": "sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/http-errors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.3.tgz", + "integrity": "sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA==", + "dev": true + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-zONci81DZYCZjiLe0r6equvZut0b+dBRPBN5kBDjsONnutYNtJMoWQ9uR2RkL1gLG9NMTzvf+29e5RFfPbeKhQ==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.2.tgz", + "integrity": "sha512-8toY6FgdltSdONav1XtUHl4LN1yTmLza+EuDazb/fEmRNCwjyqNVIQWs2IfC74IqjHkREs/nQ2FWq5kZU9IC0w==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.3.tgz", + "integrity": "sha512-1nESsePMBlf0RPRffLZi5ujYh7IH1BWL4y9pr+Bn3cJBdxz+RTP8bUFljLz9HvzhhOSWKdyBZ4DIivdL6rvgZg==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "29.5.7", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.7.tgz", + "integrity": "sha512-HLyetab6KVPSiF+7pFcUyMeLsx25LDNDemw9mGsJBkai/oouwrjTycocSDYopMEwFhN2Y4s9oPyOCZNofgSt2g==", + "dev": true, + "requires": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "@types/json-schema": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", + "dev": true + }, + "@types/mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.4.tgz", + "integrity": "sha512-1Gjee59G25MrQGk8bsNvC6fxNiRgUlGn2wlhGf95a59DrprnnHk80FIMMFG9XHMdrfsuA119ht06QPDXA1Z7tw==", + "dev": true + }, + "@types/node": { + "version": "20.8.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", + "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } + }, + "@types/qs": { + "version": "6.9.9", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", + "integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz", + "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==", + "dev": true + }, + "@types/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", + "dev": true + }, + "@types/send": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.3.tgz", + "integrity": "sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==", + "dev": true, + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/serve-static": { + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.4.tgz", + "integrity": "sha512-aqqNfs1XTF0HDrFdlY//+SGUxmdSUbjeRXb5iaZc3x0/vMbYmdw9qvOgHWOyyLFxSSRnUuP5+724zBgfw8/WAw==", + "dev": true, + "requires": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.2.tgz", + "integrity": "sha512-g7CK9nHdwjK2n0ymT2CW698FuWJRIx+RP6embAzZ2Qi8/ilIrA1Imt2LVSeHUzKvpoi7BhmmQcXz95eS0f2JXw==", + "dev": true + }, + "@types/superagent": { + "version": "4.1.20", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.20.tgz", + "integrity": "sha512-GfpwJgYSr3yO+nArFkmyqv3i0vZavyEG5xPd/o95RwpKYpsOKJYI5XLdxLpdRbZI3YiGKKdIOFIf/jlP7A0Jxg==", + "dev": true, + "requires": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "@types/supertest": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.15.tgz", + "integrity": "sha512-jUCZZ/TMcpGzoSaed9Gjr8HCf3HehExdibyw3OHHEL1als1KmyzcOZZH4MjbObI8TkWsEr7bc7gsW0WTDni+qQ==", + "dev": true, + "requires": { + "@types/superagent": "*" + } + }, + "@types/yargs": { + "version": "17.0.29", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.29.tgz", + "integrity": "sha512-nacjqA3ee9zRF/++a3FUY1suHTFKZeHba2n8WeDw9cCVdmzmHpIxyzOJBcpHvvEmS8E9KqWlSnWHUkOrkhWcvA==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.2", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.2.tgz", + "integrity": "sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.1.tgz", + "integrity": "sha512-w0tiiRc9I4S5XSXXrMHOWgHgxbrBn1Ro+PmiYhSg2ZVdxrAJtQgzU5o2m1BfP6UOn7Vxcc6152vFjQfmZR4xEg==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/type-utils": "6.9.1", + "@typescript-eslint/utils": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/parser": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.1.tgz", + "integrity": "sha512-C7AK2wn43GSaCUZ9do6Ksgi2g3mwFkMO3Cis96kzmgudoVaKyt62yNzJOktP0HDLb/iO2O0n2lBOzJgr6Q/cyg==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", + "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1" + } + }, + "@typescript-eslint/type-utils": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.1.tgz", + "integrity": "sha512-eh2oHaUKCK58qIeYp19F5V5TbpM52680sB4zNSz29VBQPTWIlE/hCj5P5B1AChxECe/fmZlspAWFuRniep1Skg==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/utils": "6.9.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/types": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", + "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", + "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/utils": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.1.tgz", + "integrity": "sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/typescript-estree": "6.9.1", + "semver": "^7.5.4" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", + "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.9.1", + "eslint-visitor-keys": "^3.4.1" + } + }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "dev": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "dev": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true + }, + "acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "dev": true, + "requires": {} + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "acorn-walk": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "dev": true + }, + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "requires": { + "ajv": "^8.0.0" + } + }, + "ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "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 + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "array-timsort": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", + "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "requires": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "dependencies": { + "istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "requires": { + "@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-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@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-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" + }, + "big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "dev": true, + "requires": { + "big-integer": "^1.6.44" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserslist": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + } + }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dev": true, + "requires": { + "run-applescript": "^5.0.0" + } + }, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "requires": { + "streamsearch": "^1.1.0" + } + }, + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "requires": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001559", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001559.tgz", + "integrity": "sha512-cPiMKZgqgkg5LY3/ntGeLFUpi6tzddBNS58A4tnTgQw1zON7u2sZMU7SzOeVH4tj20++9ggL+V6FDOFMTaFFYA==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true + }, + "ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true + }, + "cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", + "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==", + "dev": true + }, + "cli-table3": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", + "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "dev": true, + "requires": { + "@colors/colors": "1.5.0", + "string-width": "^4.2.0" + } + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true + }, + "collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "comment-json": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.3.tgz", + "integrity": "sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw==", + "dev": true, + "requires": { + "array-timsort": "^1.0.3", + "core-util-is": "^1.0.3", + "esprima": "^4.0.1", + "has-own-prop": "^2.0.0", + "repeat-string": "^1.6.1" + } + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + } + }, + "content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" + }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "requires": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + } + }, + "create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "requires": {} + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true + }, + "default-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", + "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", + "dev": true, + "requires": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^7.1.1", + "titleize": "^3.0.0" + }, + "dependencies": { + "execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + } + }, + "human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true + }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true + }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true + }, + "npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "requires": { + "path-key": "^4.0.0" + } + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true + } + } + }, + "default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "dev": true, + "requires": { + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" + } + }, + "defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "requires": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, + "define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true + }, + "dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==" + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "electron-to-chromium": { + "version": "1.4.575", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.575.tgz", + "integrity": "sha512-kY2BGyvgAHiX899oF6xLXSIf99bAvvdPhDoJwG77nxCSyWYuRH6e9a9a3gpXBvCs6lj4dQZJkfnW2hdKWHEISg==", + "dev": true + }, + "emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-module-lexer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", + "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", + "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.52.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + } + } + }, + "eslint-config-prettier": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", + "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", + "dev": true, + "requires": {} + }, + "eslint-plugin-prettier": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz", + "integrity": "sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.5" + } + }, + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "dependencies": { + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + } + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true + }, + "expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "requires": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + } + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" + }, + "fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "requires": { + "bser": "2.1.1" + } + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + } + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", + "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", + "dev": true, + "requires": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + } + }, + "fork-ts-checker-webpack-plugin": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", + "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^8.2.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" + } + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "formidable": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", + "integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==", + "dev": true, + "requires": { + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0", + "qs": "^6.11.0" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs-monkey": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", + "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "requires": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "requires": { + "get-intrinsic": "^1.1.3" + } + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "has-own-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", + "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", + "dev": true + }, + "has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "requires": { + "get-intrinsic": "^1.2.2" + } + }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "requires": { + "function-bind": "^1.1.2" + } + }, + "hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", + "dev": true + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "inquirer": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" + } + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "requires": { + "hasown": "^2.0.0" + } + }, + "is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "requires": { + "is-docker": "^3.0.0" + } + }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + }, + "dependencies": { + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true + } + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", + "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + } + }, + "istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "iterare": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", + "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==" + }, + "jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, + "jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "requires": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + } + }, + "jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "requires": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + } + }, + "jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "requires": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + } + }, + "jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "requires": { + "detect-newline": "^3.0.0" + } + }, + "jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + } + }, + "jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true + }, + "jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + } + }, + "jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "requires": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "requires": {} + }, + "jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true + }, + "jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + } + }, + "jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "requires": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + } + }, + "jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + } + }, + "jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + } + } + }, + "jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "requires": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + } + }, + "jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "requires": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "macos-release": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.1.tgz", + "integrity": "sha512-DXqXhEM7gW59OjZO8NIjBCz9AQ1BEMrfiOAl4AYByHCtVHRF4KoGNO8mqQeM8lRCtQe/UnJ4imO/d2HdkKsd+A==", + "dev": true + }, + "magic-string": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.1.tgz", + "integrity": "sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==", + "dev": true, + "requires": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "requires": { + "semver": "^7.5.3" + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "requires": { + "tmpl": "1.0.5" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "requires": { + "fs-monkey": "^1.0.4" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "multer": { + "version": "1.4.4-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz", + "integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + } + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true + }, + "node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dev": true, + "requires": { + "lodash": "^4.17.21" + } + }, + "node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "open": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", + "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", + "dev": true, + "requires": { + "default-browser": "^4.0.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^2.2.0" + } + }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + } + }, + "os-name": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-4.0.1.tgz", + "integrity": "sha512-xl9MAoU97MH1Xt5K9ERft2YfCAoaO6msy1OBA0ozxEC0x0TmIoE6K3QvgJMMZA9yKGLmHXNY/YZoDbiGDj4zYw==", + "dev": true, + "requires": { + "macos-release": "^2.5.0", + "windows-release": "^4.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "passport": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", + "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", + "requires": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + } + }, + "passport-google-oauth20": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", + "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==", + "requires": { + "passport-oauth2": "1.x.x" + } + }, + "passport-oauth2": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.7.0.tgz", + "integrity": "sha512-j2gf34szdTF2Onw3+76alNnaAExlUmHvkc7cL+cmaS5NzHzDP/BvFHJruueQ9XAeNOdpI+CH+PWid8RA7KCwAQ==", + "requires": { + "base64url": "3.x.x", + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + } + }, + "passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==" + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "requires": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", + "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "dev": true + } + } + }, + "path-to-regexp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", + "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==" + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + } + } + }, + "pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", + "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true + }, + "pure-rand": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "dev": true + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "dependencies": { + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + } + } + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", + "integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==", + "dev": true, + "requires": { + "glob": "^9.2.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + } + }, + "minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true + } + } + }, + "run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dev": true, + "requires": { + "execa": "^5.0.0" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "requires": { + "tslib": "^2.1.0" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + } + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, + "set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "requires": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "superagent": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", + "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==", + "dev": true, + "requires": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^2.1.2", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0", + "semver": "^7.3.8" + }, + "dependencies": { + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + } + } + }, + "supertest": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.3.tgz", + "integrity": "sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA==", + "dev": true, + "requires": { + "methods": "^1.1.2", + "superagent": "^8.0.5" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "dev": true + }, + "synckit": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", + "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", + "dev": true, + "requires": { + "@pkgr/utils": "^2.3.1", + "tslib": "^2.5.0" + } + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + }, + "terser": { + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", + "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.17", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" + }, + "dependencies": { + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + } + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "titleize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", + "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, + "ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "requires": {} + }, + "ts-jest": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "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" + } + }, + "ts-loader": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.0.tgz", + "integrity": "sha512-LLlB/pkB4q9mW2yLdFMnK3dEHbrBjeZTYguaaIfusyojBgAGf5kF+O6KcWqiGzWqHk0LBsoolrp4VftEURhybg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + } + }, + "ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + } + }, + "tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "requires": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true + } + } + }, + "tsconfig-paths-webpack-plugin": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.1.0.tgz", + "integrity": "sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.7.0", + "tsconfig-paths": "^4.1.2" + } + }, + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true + }, + "uid": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", + "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", + "requires": { + "@lukeed/csprng": "^1.0.0" + } + }, + "uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, + "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==", + "dev": true + }, + "universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "v8-to-istanbul": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", + "integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "requires": { + "makeerror": "1.0.12" + } + }, + "watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "webpack": { + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "dependencies": { + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + } + } + }, + "webpack-node-externals": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", + "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==", + "dev": true + }, + "webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "windows-release": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-4.0.0.tgz", + "integrity": "sha512-OxmV4wzDKB1x7AZaZgXMVsdJ1qER1ed83ZrTYd5Bwq2HfJVg3DJS8nqlAG4sMoJ7mu8cuRmLEYyU13BKwctRAg==", + "dev": true, + "requires": { + "execa": "^4.0.2" + }, + "dependencies": { + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + } + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "dependencies": { + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + } + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/back/package.json b/back/package.json new file mode 100644 index 0000000..8bdb84d --- /dev/null +++ b/back/package.json @@ -0,0 +1,73 @@ +{ + "name": "ssock", + "version": "0.0.1", + "description": "", + "author": "", + "private": true, + "license": "UNLICENSED", + "scripts": { + "build": "nest build", + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", + "start": "nest start", + "start:dev": "nest start --watch", + "start:debug": "nest start --debug --watch", + "start:prod": "node dist/main", + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", + "test": "jest", + "test:watch": "jest --watch", + "test:cov": "jest --coverage", + "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", + "test:e2e": "jest --config ./test/jest-e2e.json" + }, + "dependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/passport": "^10.0.2", + "@nestjs/platform-express": "^10.0.0", + "dotenv": "^16.3.1", + "passport": "^0.6.0", + "passport-google-oauth20": "^2.0.0", + "reflect-metadata": "^0.1.13", + "rxjs": "^7.8.1" + }, + "devDependencies": { + "@nestjs/cli": "^10.0.0", + "@nestjs/schematics": "^10.0.0", + "@nestjs/testing": "^10.0.0", + "@types/express": "^4.17.17", + "@types/jest": "^29.5.2", + "@types/node": "^20.3.1", + "@types/supertest": "^2.0.12", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "eslint": "^8.42.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "jest": "^29.5.0", + "prettier": "^3.0.0", + "source-map-support": "^0.5.21", + "supertest": "^6.3.3", + "ts-jest": "^29.1.0", + "ts-loader": "^9.4.3", + "ts-node": "^10.9.1", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.1.3" + }, + "jest": { + "moduleFileExtensions": [ + "js", + "json", + "ts" + ], + "rootDir": "src", + "testRegex": ".*\\.spec\\.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + }, + "collectCoverageFrom": [ + "**/*.(t|j)s" + ], + "coverageDirectory": "../coverage", + "testEnvironment": "node" + } +} diff --git a/back/src/app.controller.spec.ts b/back/src/app.controller.spec.ts new file mode 100644 index 0000000..c6e6584 --- /dev/null +++ b/back/src/app.controller.spec.ts @@ -0,0 +1,22 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; + +describe('AppController', () => { + let appController: AppController; + + beforeEach(async () => { + const app: TestingModule = await Test.createTestingModule({ + controllers: [AppController], + providers: [AppService] + }).compile(); + + appController = app.get(AppController); + }); + + describe('root', () => { + it('should return "Hello World!"', () => { + expect(appController.getHello()).toBe('Hello World!'); + }); + }); +}); diff --git a/back/src/app.controller.ts b/back/src/app.controller.ts new file mode 100644 index 0000000..cce879e --- /dev/null +++ b/back/src/app.controller.ts @@ -0,0 +1,12 @@ +import { Controller, Get } from '@nestjs/common'; +import { AppService } from './app.service'; + +@Controller() +export class AppController { + constructor(private readonly appService: AppService) {} + + @Get() + getHello(): string { + return this.appService.getHello(); + } +} diff --git a/back/src/app.module.ts b/back/src/app.module.ts new file mode 100644 index 0000000..4526e06 --- /dev/null +++ b/back/src/app.module.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; + +@Module({ + imports: [], + controllers: [AppController], + providers: [AppService] +}) +export class AppModule {} diff --git a/back/src/app.service.ts b/back/src/app.service.ts new file mode 100644 index 0000000..927d7cc --- /dev/null +++ b/back/src/app.service.ts @@ -0,0 +1,8 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class AppService { + getHello(): string { + return 'Hello World!'; + } +} diff --git a/back/src/main.ts b/back/src/main.ts new file mode 100644 index 0000000..5b5f35f --- /dev/null +++ b/back/src/main.ts @@ -0,0 +1,10 @@ +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; +import * as dotenv from 'dotenv'; + +async function bootstrap() { + dotenv.config(); + const app = await NestFactory.create(AppModule); + await app.listen(3000); +} +bootstrap(); diff --git a/back/test/app.e2e-spec.ts b/back/test/app.e2e-spec.ts new file mode 100644 index 0000000..50cda62 --- /dev/null +++ b/back/test/app.e2e-spec.ts @@ -0,0 +1,24 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { INestApplication } from '@nestjs/common'; +import * as request from 'supertest'; +import { AppModule } from './../src/app.module'; + +describe('AppController (e2e)', () => { + let app: INestApplication; + + beforeEach(async () => { + const moduleFixture: TestingModule = await Test.createTestingModule({ + imports: [AppModule], + }).compile(); + + app = moduleFixture.createNestApplication(); + await app.init(); + }); + + it('/ (GET)', () => { + return request(app.getHttpServer()) + .get('/') + .expect(200) + .expect('Hello World!'); + }); +}); diff --git a/back/test/jest-e2e.json b/back/test/jest-e2e.json new file mode 100644 index 0000000..e9d912f --- /dev/null +++ b/back/test/jest-e2e.json @@ -0,0 +1,9 @@ +{ + "moduleFileExtensions": ["js", "json", "ts"], + "rootDir": ".", + "testEnvironment": "node", + "testRegex": ".e2e-spec.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + } +} diff --git a/back/tsconfig.build.json b/back/tsconfig.build.json new file mode 100644 index 0000000..64f86c6 --- /dev/null +++ b/back/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] +} diff --git a/back/tsconfig.json b/back/tsconfig.json new file mode 100644 index 0000000..95f5641 --- /dev/null +++ b/back/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "ES2021", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": false, + "noImplicitAny": false, + "strictBindCallApply": false, + "forceConsistentCasingInFileNames": false, + "noFallthroughCasesInSwitch": false + } +} From 78d2f237241c00efa61b6596105ba347c3c2fa1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 7 Nov 2023 14:39:05 +0900 Subject: [PATCH 002/185] =?UTF-8?q?feat:=20Oauth2.0=20google=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EB=A1=9C=EC=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/app.module.ts | 6 ++- back/src/modules/auth/auth.controller.ts | 24 +++++++++++ back/src/modules/auth/auth.module.ts | 11 +++++ back/src/modules/auth/google-auth.service.ts | 42 ++++++++++++++++++++ 4 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 back/src/modules/auth/auth.controller.ts create mode 100644 back/src/modules/auth/auth.module.ts create mode 100644 back/src/modules/auth/google-auth.service.ts diff --git a/back/src/app.module.ts b/back/src/app.module.ts index 4526e06..a15f027 100644 --- a/back/src/app.module.ts +++ b/back/src/app.module.ts @@ -1,10 +1,12 @@ import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; +import { AuthController } from './modules/auth/auth.controller'; +import { AuthModule } from './modules/auth/auth.module'; @Module({ - imports: [], - controllers: [AppController], + imports: [AuthModule], + controllers: [AppController, AuthController], providers: [AppService] }) export class AppModule {} diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts new file mode 100644 index 0000000..a36a282 --- /dev/null +++ b/back/src/modules/auth/auth.controller.ts @@ -0,0 +1,24 @@ +import { Controller, Get, Req, Res, UseGuards } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; + +@Controller('auth') +export class AuthController { + @Get('google') + @UseGuards(AuthGuard('google')) + async googleLogin(): Promise {} + + @Get('google/redirect') + @UseGuards(AuthGuard('google')) + async googleLoginCallback(@Req() req, @Res() res): Promise { + const jwt: string = req.user.jwt; + if (jwt) { + res.redirect('http://localhost:3000/'); + } else res.redirect('http://localhost:3000/failure'); + } + + @Get('protected') + @UseGuards(AuthGuard('jwt')) + protectedResource() { + return 'JWT is working!'; + } +} diff --git a/back/src/modules/auth/auth.module.ts b/back/src/modules/auth/auth.module.ts new file mode 100644 index 0000000..91b55c4 --- /dev/null +++ b/back/src/modules/auth/auth.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { GoogleAuthService } from './google-auth.service'; +import { AuthController } from './auth.controller'; +import { PassportModule } from '@nestjs/passport'; + +@Module({ + imports: [PassportModule], + providers: [GoogleAuthService], + controllers: [AuthController] +}) +export class AuthModule {} diff --git a/back/src/modules/auth/google-auth.service.ts b/back/src/modules/auth/google-auth.service.ts new file mode 100644 index 0000000..d51b62b --- /dev/null +++ b/back/src/modules/auth/google-auth.service.ts @@ -0,0 +1,42 @@ +import { Injectable } from '@nestjs/common'; +import { PassportStrategy } from '@nestjs/passport'; +import { Strategy } from 'passport-google-oauth20'; + +@Injectable() +export class GoogleAuthService extends PassportStrategy(Strategy, 'google') { + constructor() { + super({ + clientID: `${process.env.GOOGLE_CLIENT_ID}`, + clientSecret: `${process.env.GOOGLE_SECRET}`, + callbackURL: 'http://localhost:3000/auth/google/redirect', // redirect_uri + passReqToCallback: true, + scope: ['profile'] // 가져올 정보들 + }); + } + authorizationParams(): { [key: string]: string } { + return { + access_type: 'offline', + prompt: 'select_account' + }; + } + async validate( + request: any, + accessToken: string, + refreshToken: string, + profile, + done: any + ) { + try { + console.log(profile); + + const jwt = 'placeholderJWT'; + const user = { + jwt + }; + done(null, user); + } catch (err) { + console.error(err); + done(err, false); + } + } +} From 8f132ef34ff740d2a343662098ed1fcafc1755c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 8 Nov 2023 04:07:47 +0900 Subject: [PATCH 003/185] =?UTF-8?q?feat:=20Oauth=20=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EB=B2=84=20=EC=9D=B8=EC=A6=9D=20=EB=A1=9C=EC=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.controller.ts | 19 ++++++---- back/src/modules/auth/auth.module.ts | 5 +-- ...uth.service.ts => google-auth.strategy.ts} | 10 +++--- back/src/modules/auth/naver-auth.strategy.ts | 35 +++++++++++++++++++ 4 files changed, 55 insertions(+), 14 deletions(-) rename back/src/modules/auth/{google-auth.service.ts => google-auth.strategy.ts} (81%) create mode 100644 back/src/modules/auth/naver-auth.strategy.ts diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index a36a282..79ca119 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -10,15 +10,22 @@ export class AuthController { @Get('google/redirect') @UseGuards(AuthGuard('google')) async googleLoginCallback(@Req() req, @Res() res): Promise { - const jwt: string = req.user.jwt; - if (jwt) { + const profile: string = req.user.profile; + if (profile) { res.redirect('http://localhost:3000/'); } else res.redirect('http://localhost:3000/failure'); } - @Get('protected') - @UseGuards(AuthGuard('jwt')) - protectedResource() { - return 'JWT is working!'; + @Get('naver') + @UseGuards(AuthGuard('naver')) + async snsLogin4Naver(): Promise {} + + @Get('naver/redirect') + @UseGuards(AuthGuard('naver')) + async snsLogin4NaverCallBack(@Req() req, @Res() res): Promise { + const profile: string = req.user.profile; + if (profile) { + res.redirect('http://localhost:3000/'); + } else res.redirect('http://localhost:3000/failure'); } } diff --git a/back/src/modules/auth/auth.module.ts b/back/src/modules/auth/auth.module.ts index 91b55c4..4c4fe9b 100644 --- a/back/src/modules/auth/auth.module.ts +++ b/back/src/modules/auth/auth.module.ts @@ -1,11 +1,12 @@ import { Module } from '@nestjs/common'; -import { GoogleAuthService } from './google-auth.service'; +import { GoogleAuthStrategy } from './google-auth.strategy'; +import { NaverAuthStrategy } from './naver-auth.strategy'; import { AuthController } from './auth.controller'; import { PassportModule } from '@nestjs/passport'; @Module({ imports: [PassportModule], - providers: [GoogleAuthService], + providers: [GoogleAuthStrategy, NaverAuthStrategy], controllers: [AuthController] }) export class AuthModule {} diff --git a/back/src/modules/auth/google-auth.service.ts b/back/src/modules/auth/google-auth.strategy.ts similarity index 81% rename from back/src/modules/auth/google-auth.service.ts rename to back/src/modules/auth/google-auth.strategy.ts index d51b62b..07f889c 100644 --- a/back/src/modules/auth/google-auth.service.ts +++ b/back/src/modules/auth/google-auth.strategy.ts @@ -1,9 +1,9 @@ import { Injectable } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; -import { Strategy } from 'passport-google-oauth20'; +import { Profile, Strategy } from 'passport-google-oauth20'; @Injectable() -export class GoogleAuthService extends PassportStrategy(Strategy, 'google') { +export class GoogleAuthStrategy extends PassportStrategy(Strategy, 'google') { constructor() { super({ clientID: `${process.env.GOOGLE_CLIENT_ID}`, @@ -23,15 +23,13 @@ export class GoogleAuthService extends PassportStrategy(Strategy, 'google') { request: any, accessToken: string, refreshToken: string, - profile, + profile: Profile, done: any ) { try { console.log(profile); - - const jwt = 'placeholderJWT'; const user = { - jwt + profile }; done(null, user); } catch (err) { diff --git a/back/src/modules/auth/naver-auth.strategy.ts b/back/src/modules/auth/naver-auth.strategy.ts new file mode 100644 index 0000000..bcad0d0 --- /dev/null +++ b/back/src/modules/auth/naver-auth.strategy.ts @@ -0,0 +1,35 @@ +import { Injectable } from '@nestjs/common'; +import { PassportStrategy } from '@nestjs/passport'; +import { Profile, Strategy } from 'passport-naver-v2'; + +@Injectable() +export class NaverAuthStrategy extends PassportStrategy(Strategy, 'naver') { + constructor() { + super({ + clientID: `${process.env.NAVER_CLIENT_ID}`, + clientSecret: `${process.env.NAVER_SECRET}`, + callbackURL: 'http://localhost:3000/auth/naver/redirect', // redirect_uri + passReqToCallback: true, + scope: ['profile'] // 가져올 정보들 + }); + } + + async validate( + request: any, + accessToken: string, + refreshToken: string, + profile: Profile, + done: any + ) { + try { + console.log(profile); + const user = { + profile + }; + done(null, user); + } catch (err) { + console.error(err); + done(err, false); + } + } +} From d3ae8dc98f6ccbedeef8ee2d48b391d51a60b5ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 8 Nov 2023 04:34:11 +0900 Subject: [PATCH 004/185] =?UTF-8?q?feat:=20Oauth=20=EC=B9=B4=EC=B9=B4?= =?UTF-8?q?=EC=98=A4=20strategy=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/package-lock.json | 57 ++++++++++++++++++++ back/package.json | 1 + back/src/modules/auth/auth.controller.ts | 17 +++++- back/src/modules/auth/auth.module.ts | 3 +- back/src/modules/auth/kakao-auth.strategy.ts | 35 ++++++++++++ back/src/modules/auth/naver-auth.strategy.ts | 2 +- 6 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 back/src/modules/auth/kakao-auth.strategy.ts diff --git a/back/package-lock.json b/back/package-lock.json index e2fd0ea..50105cd 100644 --- a/back/package-lock.json +++ b/back/package-lock.json @@ -16,6 +16,7 @@ "dotenv": "^16.3.1", "passport": "^0.6.0", "passport-google-oauth20": "^2.0.0", + "passport-kakao": "^1.0.1", "reflect-metadata": "^0.1.13", "rxjs": "^7.8.1" }, @@ -6778,6 +6779,28 @@ "node": ">= 0.4.0" } }, + "node_modules/passport-kakao": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/passport-kakao/-/passport-kakao-1.0.1.tgz", + "integrity": "sha512-uItaYRVrTHL6iGPMnMZvPa/O1GrAdh/V6EMjOHcFlQcVroZ9wgG7BZ5PonMNJCxfHQ3L2QVNRnzhKWUzSsumbw==", + "dependencies": { + "passport-oauth2": "~1.1.2", + "pkginfo": "~0.3.0" + } + }, + "node_modules/passport-kakao/node_modules/passport-oauth2": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.1.2.tgz", + "integrity": "sha512-wpsGtJDHHQUjyc9WcV9FFB0bphFExpmKtzkQrxpH1vnSr6RcWa3ZEGHx/zGKAh2PN7Po9TKYB1fJeOiIBspNPA==", + "dependencies": { + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/passport-oauth2": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.7.0.tgz", @@ -6973,6 +6996,14 @@ "node": ">=8" } }, + "node_modules/pkginfo": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", + "integrity": "sha512-yO5feByMzAp96LtP58wvPKSbaKAi/1C4kV9XpTctr6EepnP6F33RBNOiVrdz9BrPA98U2BMFsTNHo44TWcbQ2A==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -13937,6 +13968,27 @@ "passport-oauth2": "1.x.x" } }, + "passport-kakao": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/passport-kakao/-/passport-kakao-1.0.1.tgz", + "integrity": "sha512-uItaYRVrTHL6iGPMnMZvPa/O1GrAdh/V6EMjOHcFlQcVroZ9wgG7BZ5PonMNJCxfHQ3L2QVNRnzhKWUzSsumbw==", + "requires": { + "passport-oauth2": "~1.1.2", + "pkginfo": "~0.3.0" + }, + "dependencies": { + "passport-oauth2": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.1.2.tgz", + "integrity": "sha512-wpsGtJDHHQUjyc9WcV9FFB0bphFExpmKtzkQrxpH1vnSr6RcWa3ZEGHx/zGKAh2PN7Po9TKYB1fJeOiIBspNPA==", + "requires": { + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x" + } + } + } + }, "passport-oauth2": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.7.0.tgz", @@ -14078,6 +14130,11 @@ } } }, + "pkginfo": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", + "integrity": "sha512-yO5feByMzAp96LtP58wvPKSbaKAi/1C4kV9XpTctr6EepnP6F33RBNOiVrdz9BrPA98U2BMFsTNHo44TWcbQ2A==" + }, "pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", diff --git a/back/package.json b/back/package.json index 8bdb84d..78bae3f 100644 --- a/back/package.json +++ b/back/package.json @@ -27,6 +27,7 @@ "dotenv": "^16.3.1", "passport": "^0.6.0", "passport-google-oauth20": "^2.0.0", + "passport-kakao": "^1.0.1", "reflect-metadata": "^0.1.13", "rxjs": "^7.8.1" }, diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index 79ca119..5613f18 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -18,11 +18,24 @@ export class AuthController { @Get('naver') @UseGuards(AuthGuard('naver')) - async snsLogin4Naver(): Promise {} + async naverLogin(): Promise {} @Get('naver/redirect') @UseGuards(AuthGuard('naver')) - async snsLogin4NaverCallBack(@Req() req, @Res() res): Promise { + async naverLoginCallBack(@Req() req, @Res() res): Promise { + const profile: string = req.user.profile; + if (profile) { + res.redirect('http://localhost:3000/'); + } else res.redirect('http://localhost:3000/failure'); + } + + @Get('kakao') + @UseGuards(AuthGuard('kakao')) + async kakaologin(): Promise {} + + @Get('kakao/redirect') + @UseGuards(AuthGuard('kakao')) + async kakaologinCallBack(@Req() req, @Res() res): Promise { const profile: string = req.user.profile; if (profile) { res.redirect('http://localhost:3000/'); diff --git a/back/src/modules/auth/auth.module.ts b/back/src/modules/auth/auth.module.ts index 4c4fe9b..393b2e0 100644 --- a/back/src/modules/auth/auth.module.ts +++ b/back/src/modules/auth/auth.module.ts @@ -1,12 +1,13 @@ import { Module } from '@nestjs/common'; import { GoogleAuthStrategy } from './google-auth.strategy'; import { NaverAuthStrategy } from './naver-auth.strategy'; +import { KakaoAuthStrategy } from './kakao-auth.strategy'; import { AuthController } from './auth.controller'; import { PassportModule } from '@nestjs/passport'; @Module({ imports: [PassportModule], - providers: [GoogleAuthStrategy, NaverAuthStrategy], + providers: [GoogleAuthStrategy, NaverAuthStrategy, KakaoAuthStrategy], controllers: [AuthController] }) export class AuthModule {} diff --git a/back/src/modules/auth/kakao-auth.strategy.ts b/back/src/modules/auth/kakao-auth.strategy.ts new file mode 100644 index 0000000..e46f2f8 --- /dev/null +++ b/back/src/modules/auth/kakao-auth.strategy.ts @@ -0,0 +1,35 @@ +import { Injectable } from '@nestjs/common'; +import { PassportStrategy } from '@nestjs/passport'; +import { Profile, Strategy } from 'passport-kakao'; + +@Injectable() +export class KakaoAuthStrategy extends PassportStrategy(Strategy, 'kakao') { + constructor() { + super({ + clientID: `${process.env.KAKAO_CLIENT_ID}`, + clientSecret: `${process.env.KAKAO_SECRET}`, + callbackURL: 'http://localhost:3000/auth/kakao/redirect', // redirect_uri + passReqToCallback: true, + scope: ['profile_nickname'] + }); + } + + async validate( + request: any, + accessToken: string, + refreshToken: string, + profile: Profile, + done: any + ) { + try { + console.log(profile); + const user = { + profile + }; + done(null, user); + } catch (err) { + console.error(err); + done(err, false); + } + } +} diff --git a/back/src/modules/auth/naver-auth.strategy.ts b/back/src/modules/auth/naver-auth.strategy.ts index bcad0d0..8032bfa 100644 --- a/back/src/modules/auth/naver-auth.strategy.ts +++ b/back/src/modules/auth/naver-auth.strategy.ts @@ -10,7 +10,7 @@ export class NaverAuthStrategy extends PassportStrategy(Strategy, 'naver') { clientSecret: `${process.env.NAVER_SECRET}`, callbackURL: 'http://localhost:3000/auth/naver/redirect', // redirect_uri passReqToCallback: true, - scope: ['profile'] // 가져올 정보들 + scope: ['profile'] }); } From 7f5fb0c4262537dabb1cc9dc84317c165eb9ffb0 Mon Sep 17 00:00:00 2001 From: Mina Seo <96722691+esthel7@users.noreply.github.com> Date: Tue, 7 Nov 2023 10:07:21 +0900 Subject: [PATCH 005/185] Update README.md --- README.md | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 52af2bc..bd5aac2 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,11 @@ J074 J160 - - - - - + + + + + 김찬우 @@ -33,14 +33,6 @@ -## 협업 전략 +## [스프린트 계획회의](https://github.com/boostcampwm2023/web11-SSOCK/wiki) -## 그라운드롤 - -## [기획/디자인]() - -## [Commit Convention]() - -## [스프린트 계획회의](https://github.com/boostcampwm2023/web11-SSOCK/wiki/%F0%9F%92%A1-%EC%8A%A4%ED%94%84%EB%A6%B0%ED%8A%B8-%EA%B3%84%ED%9A%8D%ED%9A%8C%EC%9D%98-%E2%80%90-MON) - -## [데일리 스크럼](https://github.com/boostcampwm2023/web11-SSOCK/wiki/%F0%9F%97%A3%EF%B8%8F-%EB%8D%B0%EC%9D%BC%EB%A6%AC-%EC%8A%A4%ED%81%AC%EB%9F%BC) +## [Notion](https://delicious-halloumi-7ae.notion.site/SSOCK-By-SSOCK-ada468a8b135435bb8acc1c50a2a9c0c?pvs=4) From 9498a868b27423f90947b8e262dc30f8a0f3b6ee Mon Sep 17 00:00:00 2001 From: Mina Seo <96722691+esthel7@users.noreply.github.com> Date: Tue, 7 Nov 2023 10:08:04 +0900 Subject: [PATCH 006/185] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bd5aac2..4a0f103 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🎄 web11-SSOCK - +
From c8216e50997c0d9d7a845ce0065635fea1eb053c Mon Sep 17 00:00:00 2001 From: Mina Seo <96722691+esthel7@users.noreply.github.com> Date: Wed, 8 Nov 2023 16:16:15 +0900 Subject: [PATCH 007/185] Create pull_request_template.md --- .github/pull_request_template.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..6eac72c --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,8 @@ +## 완료된 기능 +- [ ] 내용 작성작성 + - 내용 작성작성📝 + +## 완료된 기능 사진 +
+ +
From 031a908accc81fce308b72d13b473e36468feae2 Mon Sep 17 00:00:00 2001 From: Mina Seo <96722691+esthel7@users.noreply.github.com> Date: Wed, 8 Nov 2023 16:22:47 +0900 Subject: [PATCH 008/185] Create issue-template.md --- .github/ISSUE_TEMPLATE/issue-template.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/issue-template.md diff --git a/.github/ISSUE_TEMPLATE/issue-template.md b/.github/ISSUE_TEMPLATE/issue-template.md new file mode 100644 index 0000000..a9fa57c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue-template.md @@ -0,0 +1,5 @@ +## 💦 이슈 설명 +- 이슈 설명설명 + +## ❗ 문제 해결 +- [ ] 문제가 일어난 파일들 From b8e60edc7e1f40de8a6333edb8d2a9e22fe99bda Mon Sep 17 00:00:00 2001 From: Mina Seo <96722691+esthel7@users.noreply.github.com> Date: Wed, 8 Nov 2023 16:23:28 +0900 Subject: [PATCH 009/185] Update pull_request_template.md --- .github/pull_request_template.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 6eac72c..9e56cf7 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,8 +1,8 @@ -## 완료된 기능 +## 💡 완료된 기능 - [ ] 내용 작성작성 - 내용 작성작성📝 -## 완료된 기능 사진 +## 📷 완료된 기능 사진
From 1b555f04fc7e213f8736105d2e09d340747c4f08 Mon Sep 17 00:00:00 2001 From: Mina Seo <96722691+esthel7@users.noreply.github.com> Date: Wed, 8 Nov 2023 16:25:59 +0900 Subject: [PATCH 010/185] Create issue-template.md --- .github/issue-template.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/issue-template.md diff --git a/.github/issue-template.md b/.github/issue-template.md new file mode 100644 index 0000000..a9fa57c --- /dev/null +++ b/.github/issue-template.md @@ -0,0 +1,5 @@ +## 💦 이슈 설명 +- 이슈 설명설명 + +## ❗ 문제 해결 +- [ ] 문제가 일어난 파일들 From 1488f91b33ac98bd762162a810aceea245eb84b5 Mon Sep 17 00:00:00 2001 From: ChanWoo Kim Date: Wed, 8 Nov 2023 16:26:40 +0900 Subject: [PATCH 011/185] Delete .github/ISSUE_TEMPLATE directory --- .github/ISSUE_TEMPLATE/issue-template.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/issue-template.md diff --git a/.github/ISSUE_TEMPLATE/issue-template.md b/.github/ISSUE_TEMPLATE/issue-template.md deleted file mode 100644 index a9fa57c..0000000 --- a/.github/ISSUE_TEMPLATE/issue-template.md +++ /dev/null @@ -1,5 +0,0 @@ -## 💦 이슈 설명 -- 이슈 설명설명 - -## ❗ 문제 해결 -- [ ] 문제가 일어난 파일들 From 0b5ace12e3be888ec305ad3ffc845f5ba8bc2a31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Thu, 9 Nov 2023 17:01:11 +0900 Subject: [PATCH 012/185] =?UTF-8?q?feat:=20swagger=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20api=20=EA=B5=AC=EC=A1=B0=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/package-lock.json | 74 +++++++++++++++++++ back/package.json | 2 + back/src/app.controller.ts | 14 +++- back/src/app.service.ts | 5 +- back/src/dtoTest.ts | 16 ++++ back/src/main.ts | 2 + back/src/modules/auth/auth.controller.ts | 11 ++- back/src/modules/auth/google-auth.strategy.ts | 2 +- .../message/message.controller.spec.ts | 18 +++++ .../src/modules/message/message.controller.ts | 4 + back/src/modules/message/message.module.ts | 9 +++ .../modules/message/message.service.spec.ts | 18 +++++ back/src/modules/message/message.service.ts | 4 + .../modules/share/share.controller.spec.ts | 18 +++++ back/src/modules/share/share.controller.ts | 4 + back/src/modules/share/share.module.ts | 9 +++ back/src/modules/share/share.service.spec.ts | 18 +++++ back/src/modules/share/share.service.ts | 4 + .../snowball/snowball.controller.spec.ts | 18 +++++ .../modules/snowball/snowball.controller.ts | 4 + back/src/modules/snowball/snowball.module.ts | 9 +++ .../modules/snowball/snowball.service.spec.ts | 18 +++++ back/src/modules/snowball/snowball.service.ts | 4 + back/src/util/swagger.ts | 14 ++++ 24 files changed, 290 insertions(+), 9 deletions(-) create mode 100644 back/src/dtoTest.ts create mode 100644 back/src/modules/message/message.controller.spec.ts create mode 100644 back/src/modules/message/message.controller.ts create mode 100644 back/src/modules/message/message.module.ts create mode 100644 back/src/modules/message/message.service.spec.ts create mode 100644 back/src/modules/message/message.service.ts create mode 100644 back/src/modules/share/share.controller.spec.ts create mode 100644 back/src/modules/share/share.controller.ts create mode 100644 back/src/modules/share/share.module.ts create mode 100644 back/src/modules/share/share.service.spec.ts create mode 100644 back/src/modules/share/share.service.ts create mode 100644 back/src/modules/snowball/snowball.controller.spec.ts create mode 100644 back/src/modules/snowball/snowball.controller.ts create mode 100644 back/src/modules/snowball/snowball.module.ts create mode 100644 back/src/modules/snowball/snowball.service.spec.ts create mode 100644 back/src/modules/snowball/snowball.service.ts create mode 100644 back/src/util/swagger.ts diff --git a/back/package-lock.json b/back/package-lock.json index 50105cd..eccd8d9 100644 --- a/back/package-lock.json +++ b/back/package-lock.json @@ -13,8 +13,10 @@ "@nestjs/core": "^10.0.0", "@nestjs/passport": "^10.0.2", "@nestjs/platform-express": "^10.0.0", + "class-validator": "^0.14.0", "dotenv": "^16.3.1", "passport": "^0.6.0", + "passport-facebook": "^3.0.0", "passport-google-oauth20": "^2.0.0", "passport-kakao": "^1.0.1", "reflect-metadata": "^0.1.13", @@ -2102,6 +2104,11 @@ "@types/superagent": "*" } }, + "node_modules/@types/validator": { + "version": "13.11.6", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.6.tgz", + "integrity": "sha512-HUgHujPhKuNzgNXBRZKYexwoG+gHKU+tnfPqjWXFghZAnn73JElicMkuSKJyLGr9JgyA8IgK7fj88IyA9rwYeQ==" + }, "node_modules/@types/yargs": { "version": "17.0.29", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.29.tgz", @@ -3192,6 +3199,16 @@ "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, + "node_modules/class-validator": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz", + "integrity": "sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==", + "dependencies": { + "@types/validator": "^13.7.10", + "libphonenumber-js": "^1.10.14", + "validator": "^13.7.0" + } + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -6152,6 +6169,11 @@ "node": ">= 0.8.0" } }, + "node_modules/libphonenumber-js": { + "version": "1.10.49", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.49.tgz", + "integrity": "sha512-gvLtyC3tIuqfPzjvYLH9BmVdqzGDiSi4VjtWe2fAgSdBf0yt8yPmbNnRIHNbR5IdtVkm0ayGuzwQKTWmU0hdjQ==" + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -6768,6 +6790,17 @@ "url": "https://github.com/sponsors/jaredhanson" } }, + "node_modules/passport-facebook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/passport-facebook/-/passport-facebook-3.0.0.tgz", + "integrity": "sha512-K/qNzuFsFISYAyC1Nma4qgY/12V3RSLFdFVsPKXiKZt434wOvthFW1p7zKa1iQihQMRhaWorVE1o3Vi1o+ZgeQ==", + "dependencies": { + "passport-oauth2": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/passport-google-oauth20": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", @@ -8615,6 +8648,14 @@ "node": ">=10.12.0" } }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -10550,6 +10591,11 @@ "@types/superagent": "*" } }, + "@types/validator": { + "version": "13.11.6", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.6.tgz", + "integrity": "sha512-HUgHujPhKuNzgNXBRZKYexwoG+gHKU+tnfPqjWXFghZAnn73JElicMkuSKJyLGr9JgyA8IgK7fj88IyA9rwYeQ==" + }, "@types/yargs": { "version": "17.0.29", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.29.tgz", @@ -11334,6 +11380,16 @@ "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, + "class-validator": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz", + "integrity": "sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==", + "requires": { + "@types/validator": "^13.7.10", + "libphonenumber-js": "^1.10.14", + "validator": "^13.7.0" + } + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -13512,6 +13568,11 @@ "type-check": "~0.4.0" } }, + "libphonenumber-js": { + "version": "1.10.49", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.49.tgz", + "integrity": "sha512-gvLtyC3tIuqfPzjvYLH9BmVdqzGDiSi4VjtWe2fAgSdBf0yt8yPmbNnRIHNbR5IdtVkm0ayGuzwQKTWmU0hdjQ==" + }, "lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -13960,6 +14021,14 @@ "utils-merge": "^1.0.1" } }, + "passport-facebook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/passport-facebook/-/passport-facebook-3.0.0.tgz", + "integrity": "sha512-K/qNzuFsFISYAyC1Nma4qgY/12V3RSLFdFVsPKXiKZt434wOvthFW1p7zKa1iQihQMRhaWorVE1o3Vi1o+ZgeQ==", + "requires": { + "passport-oauth2": "1.x.x" + } + }, "passport-google-oauth20": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", @@ -15272,6 +15341,11 @@ "convert-source-map": "^2.0.0" } }, + "validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/back/package.json b/back/package.json index 78bae3f..1a730a0 100644 --- a/back/package.json +++ b/back/package.json @@ -24,8 +24,10 @@ "@nestjs/core": "^10.0.0", "@nestjs/passport": "^10.0.2", "@nestjs/platform-express": "^10.0.0", + "class-validator": "^0.14.0", "dotenv": "^16.3.1", "passport": "^0.6.0", + "passport-facebook": "^3.0.0", "passport-google-oauth20": "^2.0.0", "passport-kakao": "^1.0.1", "reflect-metadata": "^0.1.13", diff --git a/back/src/app.controller.ts b/back/src/app.controller.ts index cce879e..a4dd07b 100644 --- a/back/src/app.controller.ts +++ b/back/src/app.controller.ts @@ -1,12 +1,18 @@ -import { Controller, Get } from '@nestjs/common'; +import { Controller, Post, Body } from '@nestjs/common'; import { AppService } from './app.service'; +import { CreateUserDTO } from './dtoTest'; +import { ApiResponse, ApiBody } from '@nestjs/swagger'; @Controller() export class AppController { constructor(private readonly appService: AppService) {} - @Get() - getHello(): string { - return this.appService.getHello(); + @Post('/register') + @ApiResponse({ + description: '회원가입 API' + }) + @ApiBody({ type: CreateUserDTO }) + getUser(@Body() userData: CreateUserDTO): CreateUserDTO { + return this.appService.register(userData); } } diff --git a/back/src/app.service.ts b/back/src/app.service.ts index 927d7cc..40ea3bb 100644 --- a/back/src/app.service.ts +++ b/back/src/app.service.ts @@ -1,8 +1,9 @@ import { Injectable } from '@nestjs/common'; +import { CreateUserDTO } from './dtoTest'; @Injectable() export class AppService { - getHello(): string { - return 'Hello World!'; + register(userData: CreateUserDTO): CreateUserDTO { + return userData; } } diff --git a/back/src/dtoTest.ts b/back/src/dtoTest.ts new file mode 100644 index 0000000..30b6b9c --- /dev/null +++ b/back/src/dtoTest.ts @@ -0,0 +1,16 @@ +import { IsString } from 'class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class CreateUserDTO { + @IsString() + @ApiProperty({ type: String, description: '유저 ID' }) + readonly user_id: string; + + @IsString() + @ApiProperty({ type: String, description: '유저 Password' }) + readonly password: string; + + @IsString() + @ApiProperty({ type: String, description: '유저 Nickname' }) + readonly nickname: string; +} diff --git a/back/src/main.ts b/back/src/main.ts index 5b5f35f..e003b2a 100644 --- a/back/src/main.ts +++ b/back/src/main.ts @@ -1,10 +1,12 @@ import { NestFactory } from '@nestjs/core'; +import { setupSwagger } from 'src/util/swagger'; import { AppModule } from './app.module'; import * as dotenv from 'dotenv'; async function bootstrap() { dotenv.config(); const app = await NestFactory.create(AppModule); + setupSwagger(app); await app.listen(3000); } bootstrap(); diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index 5613f18..1b2b3e1 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -1,9 +1,16 @@ import { Controller, Get, Req, Res, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; +import { ApiTags, ApiOperation, ApiOAuth2 } from '@nestjs/swagger'; +@ApiTags('Oauth API') @Controller('auth') export class AuthController { @Get('google') + @ApiOperation({ + summary: 'Google 로그인 요청 API', + description: 'Google Oauth api에 로그인 요청을 보낸다.' + }) + @ApiOAuth2([]) @UseGuards(AuthGuard('google')) async googleLogin(): Promise {} @@ -31,11 +38,11 @@ export class AuthController { @Get('kakao') @UseGuards(AuthGuard('kakao')) - async kakaologin(): Promise {} + async kakaoLogin(): Promise {} @Get('kakao/redirect') @UseGuards(AuthGuard('kakao')) - async kakaologinCallBack(@Req() req, @Res() res): Promise { + async kakaoLoginCallBack(@Req() req, @Res() res): Promise { const profile: string = req.user.profile; if (profile) { res.redirect('http://localhost:3000/'); diff --git a/back/src/modules/auth/google-auth.strategy.ts b/back/src/modules/auth/google-auth.strategy.ts index 07f889c..a9ae90b 100644 --- a/back/src/modules/auth/google-auth.strategy.ts +++ b/back/src/modules/auth/google-auth.strategy.ts @@ -10,7 +10,7 @@ export class GoogleAuthStrategy extends PassportStrategy(Strategy, 'google') { clientSecret: `${process.env.GOOGLE_SECRET}`, callbackURL: 'http://localhost:3000/auth/google/redirect', // redirect_uri passReqToCallback: true, - scope: ['profile'] // 가져올 정보들 + scope: ['profile'] }); } authorizationParams(): { [key: string]: string } { diff --git a/back/src/modules/message/message.controller.spec.ts b/back/src/modules/message/message.controller.spec.ts new file mode 100644 index 0000000..4e2fe4c --- /dev/null +++ b/back/src/modules/message/message.controller.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { MessageController } from './message.controller'; + +describe('MessageController', () => { + let controller: MessageController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [MessageController], + }).compile(); + + controller = module.get(MessageController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts new file mode 100644 index 0000000..67ae776 --- /dev/null +++ b/back/src/modules/message/message.controller.ts @@ -0,0 +1,4 @@ +import { Controller } from '@nestjs/common'; + +@Controller('message') +export class MessageController {} diff --git a/back/src/modules/message/message.module.ts b/back/src/modules/message/message.module.ts new file mode 100644 index 0000000..f6d7999 --- /dev/null +++ b/back/src/modules/message/message.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { MessageController } from './message.controller'; +import { MessageService } from './message.service'; + +@Module({ + controllers: [MessageController], + providers: [MessageService] +}) +export class MessageModule {} diff --git a/back/src/modules/message/message.service.spec.ts b/back/src/modules/message/message.service.spec.ts new file mode 100644 index 0000000..fffdd9c --- /dev/null +++ b/back/src/modules/message/message.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { MessageService } from './message.service'; + +describe('MessageService', () => { + let service: MessageService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [MessageService], + }).compile(); + + service = module.get(MessageService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts new file mode 100644 index 0000000..65fe564 --- /dev/null +++ b/back/src/modules/message/message.service.ts @@ -0,0 +1,4 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class MessageService {} diff --git a/back/src/modules/share/share.controller.spec.ts b/back/src/modules/share/share.controller.spec.ts new file mode 100644 index 0000000..bc917dd --- /dev/null +++ b/back/src/modules/share/share.controller.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { ShareController } from './share.controller'; + +describe('ShareController', () => { + let controller: ShareController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [ShareController], + }).compile(); + + controller = module.get(ShareController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/back/src/modules/share/share.controller.ts b/back/src/modules/share/share.controller.ts new file mode 100644 index 0000000..b304478 --- /dev/null +++ b/back/src/modules/share/share.controller.ts @@ -0,0 +1,4 @@ +import { Controller } from '@nestjs/common'; + +@Controller('share') +export class ShareController {} diff --git a/back/src/modules/share/share.module.ts b/back/src/modules/share/share.module.ts new file mode 100644 index 0000000..0b021de --- /dev/null +++ b/back/src/modules/share/share.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { ShareController } from './share.controller'; +import { ShareService } from './share.service'; + +@Module({ + controllers: [ShareController], + providers: [ShareService] +}) +export class ShareModule {} diff --git a/back/src/modules/share/share.service.spec.ts b/back/src/modules/share/share.service.spec.ts new file mode 100644 index 0000000..62d3afc --- /dev/null +++ b/back/src/modules/share/share.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { ShareService } from './share.service'; + +describe('ShareService', () => { + let service: ShareService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ShareService], + }).compile(); + + service = module.get(ShareService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/back/src/modules/share/share.service.ts b/back/src/modules/share/share.service.ts new file mode 100644 index 0000000..e55cb2d --- /dev/null +++ b/back/src/modules/share/share.service.ts @@ -0,0 +1,4 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class ShareService {} diff --git a/back/src/modules/snowball/snowball.controller.spec.ts b/back/src/modules/snowball/snowball.controller.spec.ts new file mode 100644 index 0000000..e4e8a79 --- /dev/null +++ b/back/src/modules/snowball/snowball.controller.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { SnowballController } from './snowball.controller'; + +describe('SnowballController', () => { + let controller: SnowballController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [SnowballController], + }).compile(); + + controller = module.get(SnowballController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts new file mode 100644 index 0000000..dd40223 --- /dev/null +++ b/back/src/modules/snowball/snowball.controller.ts @@ -0,0 +1,4 @@ +import { Controller } from '@nestjs/common'; + +@Controller('snowball') +export class SnowballController {} diff --git a/back/src/modules/snowball/snowball.module.ts b/back/src/modules/snowball/snowball.module.ts new file mode 100644 index 0000000..197fdad --- /dev/null +++ b/back/src/modules/snowball/snowball.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { SnowballController } from './snowball.controller'; +import { SnowballService } from './snowball.service'; + +@Module({ + controllers: [SnowballController], + providers: [SnowballService] +}) +export class SnowballModule {} diff --git a/back/src/modules/snowball/snowball.service.spec.ts b/back/src/modules/snowball/snowball.service.spec.ts new file mode 100644 index 0000000..622d529 --- /dev/null +++ b/back/src/modules/snowball/snowball.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { SnowballService } from './snowball.service'; + +describe('SnowballService', () => { + let service: SnowballService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [SnowballService], + }).compile(); + + service = module.get(SnowballService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts new file mode 100644 index 0000000..e9ef044 --- /dev/null +++ b/back/src/modules/snowball/snowball.service.ts @@ -0,0 +1,4 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class SnowballService {} diff --git a/back/src/util/swagger.ts b/back/src/util/swagger.ts new file mode 100644 index 0000000..43c9452 --- /dev/null +++ b/back/src/util/swagger.ts @@ -0,0 +1,14 @@ +import { INestApplication } from '@nestjs/common'; +import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; + +export function setupSwagger(app: INestApplication): void { + const config = new DocumentBuilder() + .setTitle('SSOCK API') + .setDescription('The SSOCK API description') + .setVersion('1.0') + .addTag('ssock') + .addOAuth2() + .build(); + const document = SwaggerModule.createDocument(app, config); + SwaggerModule.setup('api', app, document); +} From ac1895bd081cdc64f810c96495c41985360f2226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Fri, 10 Nov 2023 19:22:35 +0900 Subject: [PATCH 013/185] =?UTF-8?q?feat:=20oauth=20swagger=20api=20?= =?UTF-8?q?=EB=AA=85=EC=84=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/app.controller.spec.ts | 22 --------- back/src/modules/auth/auth.controller.ts | 45 +++++++++++++++++-- .../message/message.controller.spec.ts | 18 -------- .../modules/message/message.service.spec.ts | 18 -------- .../modules/share/share.controller.spec.ts | 18 -------- back/src/modules/share/share.service.spec.ts | 18 -------- .../snowball/snowball.controller.spec.ts | 18 -------- .../modules/snowball/snowball.service.spec.ts | 18 -------- back/src/util/swagger.ts | 1 - 9 files changed, 42 insertions(+), 134 deletions(-) delete mode 100644 back/src/app.controller.spec.ts delete mode 100644 back/src/modules/message/message.controller.spec.ts delete mode 100644 back/src/modules/message/message.service.spec.ts delete mode 100644 back/src/modules/share/share.controller.spec.ts delete mode 100644 back/src/modules/share/share.service.spec.ts delete mode 100644 back/src/modules/snowball/snowball.controller.spec.ts delete mode 100644 back/src/modules/snowball/snowball.service.spec.ts diff --git a/back/src/app.controller.spec.ts b/back/src/app.controller.spec.ts deleted file mode 100644 index c6e6584..0000000 --- a/back/src/app.controller.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AppController } from './app.controller'; -import { AppService } from './app.service'; - -describe('AppController', () => { - let appController: AppController; - - beforeEach(async () => { - const app: TestingModule = await Test.createTestingModule({ - controllers: [AppController], - providers: [AppService] - }).compile(); - - appController = app.get(AppController); - }); - - describe('root', () => { - it('should return "Hello World!"', () => { - expect(appController.getHello()).toBe('Hello World!'); - }); - }); -}); diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index 1b2b3e1..bc1c0d4 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -1,6 +1,11 @@ import { Controller, Get, Req, Res, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; -import { ApiTags, ApiOperation, ApiOAuth2 } from '@nestjs/swagger'; +import { + ApiTags, + ApiOperation, + ApiExcludeEndpoint, + ApiResponse +} from '@nestjs/swagger'; @ApiTags('Oauth API') @Controller('auth') @@ -8,13 +13,21 @@ export class AuthController { @Get('google') @ApiOperation({ summary: 'Google 로그인 요청 API', - description: 'Google Oauth api에 로그인 요청을 보낸다.' + description: 'Google OAuth API에 로그인 요청을 보냅니다.' + }) + @ApiResponse({ + status: 200, + description: `'http://localhost:3000/'으로 리다이렉트` + }) + @ApiResponse({ + status: 400, + description: `'http://localhost:3000/failure'으로 리다이렉트` }) - @ApiOAuth2([]) @UseGuards(AuthGuard('google')) async googleLogin(): Promise {} @Get('google/redirect') + @ApiExcludeEndpoint() @UseGuards(AuthGuard('google')) async googleLoginCallback(@Req() req, @Res() res): Promise { const profile: string = req.user.profile; @@ -24,10 +37,23 @@ export class AuthController { } @Get('naver') + @ApiOperation({ + summary: 'Naver 로그인 요청 API', + description: 'Naver OAuth API에 로그인 요청을 보냅니다.' + }) + @ApiResponse({ + status: 200, + description: `'http://localhost:3000/'으로 리다이렉트` + }) + @ApiResponse({ + status: 400, + description: `'http://localhost:3000/failure'으로 리다이렉트` + }) @UseGuards(AuthGuard('naver')) async naverLogin(): Promise {} @Get('naver/redirect') + @ApiExcludeEndpoint() @UseGuards(AuthGuard('naver')) async naverLoginCallBack(@Req() req, @Res() res): Promise { const profile: string = req.user.profile; @@ -37,10 +63,23 @@ export class AuthController { } @Get('kakao') + @ApiOperation({ + summary: 'Kakao 로그인 요청 API', + description: 'Kakao OAuth API에 로그인 요청을 보냅니다.' + }) + @ApiResponse({ + status: 200, + description: `'http://localhost:3000/'으로 리다이렉트` + }) + @ApiResponse({ + status: 400, + description: `'http://localhost:3000/failure'으로 리다이렉트` + }) @UseGuards(AuthGuard('kakao')) async kakaoLogin(): Promise {} @Get('kakao/redirect') + @ApiExcludeEndpoint() @UseGuards(AuthGuard('kakao')) async kakaoLoginCallBack(@Req() req, @Res() res): Promise { const profile: string = req.user.profile; diff --git a/back/src/modules/message/message.controller.spec.ts b/back/src/modules/message/message.controller.spec.ts deleted file mode 100644 index 4e2fe4c..0000000 --- a/back/src/modules/message/message.controller.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { MessageController } from './message.controller'; - -describe('MessageController', () => { - let controller: MessageController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [MessageController], - }).compile(); - - controller = module.get(MessageController); - }); - - it('should be defined', () => { - expect(controller).toBeDefined(); - }); -}); diff --git a/back/src/modules/message/message.service.spec.ts b/back/src/modules/message/message.service.spec.ts deleted file mode 100644 index fffdd9c..0000000 --- a/back/src/modules/message/message.service.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { MessageService } from './message.service'; - -describe('MessageService', () => { - let service: MessageService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [MessageService], - }).compile(); - - service = module.get(MessageService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/back/src/modules/share/share.controller.spec.ts b/back/src/modules/share/share.controller.spec.ts deleted file mode 100644 index bc917dd..0000000 --- a/back/src/modules/share/share.controller.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { ShareController } from './share.controller'; - -describe('ShareController', () => { - let controller: ShareController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [ShareController], - }).compile(); - - controller = module.get(ShareController); - }); - - it('should be defined', () => { - expect(controller).toBeDefined(); - }); -}); diff --git a/back/src/modules/share/share.service.spec.ts b/back/src/modules/share/share.service.spec.ts deleted file mode 100644 index 62d3afc..0000000 --- a/back/src/modules/share/share.service.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { ShareService } from './share.service'; - -describe('ShareService', () => { - let service: ShareService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ShareService], - }).compile(); - - service = module.get(ShareService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/back/src/modules/snowball/snowball.controller.spec.ts b/back/src/modules/snowball/snowball.controller.spec.ts deleted file mode 100644 index e4e8a79..0000000 --- a/back/src/modules/snowball/snowball.controller.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { SnowballController } from './snowball.controller'; - -describe('SnowballController', () => { - let controller: SnowballController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [SnowballController], - }).compile(); - - controller = module.get(SnowballController); - }); - - it('should be defined', () => { - expect(controller).toBeDefined(); - }); -}); diff --git a/back/src/modules/snowball/snowball.service.spec.ts b/back/src/modules/snowball/snowball.service.spec.ts deleted file mode 100644 index 622d529..0000000 --- a/back/src/modules/snowball/snowball.service.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { SnowballService } from './snowball.service'; - -describe('SnowballService', () => { - let service: SnowballService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [SnowballService], - }).compile(); - - service = module.get(SnowballService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/back/src/util/swagger.ts b/back/src/util/swagger.ts index 43c9452..94b2fef 100644 --- a/back/src/util/swagger.ts +++ b/back/src/util/swagger.ts @@ -7,7 +7,6 @@ export function setupSwagger(app: INestApplication): void { .setDescription('The SSOCK API description') .setVersion('1.0') .addTag('ssock') - .addOAuth2() .build(); const document = SwaggerModule.createDocument(app, config); SwaggerModule.setup('api', app, document); From 686e04490d3f45ea2dce905cb322adf73ab75040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Sat, 11 Nov 2023 04:14:15 +0900 Subject: [PATCH 014/185] =?UTF-8?q?feat:=20message=20create=20dto=20&=20en?= =?UTF-8?q?tity=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/app.controller.ts | 17 ++----- back/src/app.module.ts | 9 ++-- back/src/app.service.ts | 7 +-- back/src/dtoTest.ts | 16 ------- .../modules/message/dto/create-message.dto.ts | 24 ++++++++++ .../modules/message/entity/message.entity.ts | 46 +++++++++++++++++++ .../src/modules/message/message.controller.ts | 19 +++++++- back/src/modules/message/message.service.ts | 7 ++- 8 files changed, 104 insertions(+), 41 deletions(-) delete mode 100644 back/src/dtoTest.ts create mode 100644 back/src/modules/message/dto/create-message.dto.ts create mode 100644 back/src/modules/message/entity/message.entity.ts diff --git a/back/src/app.controller.ts b/back/src/app.controller.ts index a4dd07b..5b90d26 100644 --- a/back/src/app.controller.ts +++ b/back/src/app.controller.ts @@ -1,18 +1,9 @@ -import { Controller, Post, Body } from '@nestjs/common'; -import { AppService } from './app.service'; -import { CreateUserDTO } from './dtoTest'; -import { ApiResponse, ApiBody } from '@nestjs/swagger'; +import { Controller, Get } from '@nestjs/common'; @Controller() export class AppController { - constructor(private readonly appService: AppService) {} - - @Post('/register') - @ApiResponse({ - description: '회원가입 API' - }) - @ApiBody({ type: CreateUserDTO }) - getUser(@Body() userData: CreateUserDTO): CreateUserDTO { - return this.appService.register(userData); + @Get() + getHello(): string { + return 'Hello, World!'; } } diff --git a/back/src/app.module.ts b/back/src/app.module.ts index a15f027..f3fdaf6 100644 --- a/back/src/app.module.ts +++ b/back/src/app.module.ts @@ -3,10 +3,13 @@ import { AppController } from './app.controller'; import { AppService } from './app.service'; import { AuthController } from './modules/auth/auth.controller'; import { AuthModule } from './modules/auth/auth.module'; +import { MessageController } from './modules/message/message.controller'; +import { MessageModule } from './modules/message/message.module'; +import { MessageService } from './modules/message/message.service'; @Module({ - imports: [AuthModule], - controllers: [AppController, AuthController], - providers: [AppService] + imports: [AuthModule, MessageModule], + controllers: [AppController, AuthController, MessageController], + providers: [AppService, MessageService] }) export class AppModule {} diff --git a/back/src/app.service.ts b/back/src/app.service.ts index 40ea3bb..7263d33 100644 --- a/back/src/app.service.ts +++ b/back/src/app.service.ts @@ -1,9 +1,4 @@ import { Injectable } from '@nestjs/common'; -import { CreateUserDTO } from './dtoTest'; @Injectable() -export class AppService { - register(userData: CreateUserDTO): CreateUserDTO { - return userData; - } -} +export class AppService {} diff --git a/back/src/dtoTest.ts b/back/src/dtoTest.ts deleted file mode 100644 index 30b6b9c..0000000 --- a/back/src/dtoTest.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { IsString } from 'class-validator'; -import { ApiProperty } from '@nestjs/swagger'; - -export class CreateUserDTO { - @IsString() - @ApiProperty({ type: String, description: '유저 ID' }) - readonly user_id: string; - - @IsString() - @ApiProperty({ type: String, description: '유저 Password' }) - readonly password: string; - - @IsString() - @ApiProperty({ type: String, description: '유저 Nickname' }) - readonly nickname: string; -} diff --git a/back/src/modules/message/dto/create-message.dto.ts b/back/src/modules/message/dto/create-message.dto.ts new file mode 100644 index 0000000..98ff184 --- /dev/null +++ b/back/src/modules/message/dto/create-message.dto.ts @@ -0,0 +1,24 @@ +import { IsString, IsNumber, IsNotEmpty } from 'class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class CreateMessageDto { + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '메세지 내용' }) + readonly content: string; + + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '스노우볼 id' }) + readonly snowball_id: number; + + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '장식 id' }) + readonly deco_id: number; + + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '익명 사용자 닉네임(From)' }) + readonly sender: string; +} diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts new file mode 100644 index 0000000..73219c9 --- /dev/null +++ b/back/src/modules/message/entity/message.entity.ts @@ -0,0 +1,46 @@ +import { IsString, IsNumber, IsDateString, IsNotEmpty } from 'class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class CreateMessageDto { + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '메세지 내용' }) + readonly content: string; + + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '스노우볼 id' }) + readonly snowball_id: number; + + @IsDateString() + @ApiProperty({ + type: String, + description: '비공개 설정 시간, 공개 시 null로 설정' + }) + readonly private: string | null; + + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '장식 id' }) + readonly deco_id: number; + + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '익명 사용자 닉네임(From)' }) + readonly sender: string; + + @IsDateString() + @ApiProperty({ + type: String, + description: '메세지 열람 시간, 비열람 시 null로 설정' + }) + readonly opened: string | null; + + @IsDateString() + @IsNotEmpty() + @ApiProperty({ + type: String, + description: '메세지 생성 시간' + }) + readonly created_at: string; +} diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 67ae776..03d0df8 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -1,4 +1,19 @@ -import { Controller } from '@nestjs/common'; +import { Controller, Post, Body } from '@nestjs/common'; +import { MessageService } from './message.service'; +import { CreateMessageDto } from './dto/create-message.dto'; +import { ApiResponse, ApiBody, ApiTags } from '@nestjs/swagger'; +@ApiTags('Message API') @Controller('message') -export class MessageController {} +export class MessageController { + constructor(private readonly messageService: MessageService) {} + + @Post('write') + @ApiResponse({ + description: '메세지 생성 API' + }) + @ApiBody({ type: CreateMessageDto }) + createMessage(@Body() createMessageDto: CreateMessageDto) { + return this.messageService.createMessage(createMessageDto); + } +} diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 65fe564..a72fc10 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -1,4 +1,9 @@ import { Injectable } from '@nestjs/common'; +import { CreateMessageDto } from './dto/create-message.dto'; @Injectable() -export class MessageService {} +export class MessageService { + createMessage(createMessageDto: CreateMessageDto) { + return createMessageDto; + } +} From 8c7746b3fc46fcf3ec2467322426b62cfb72ce40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Sat, 11 Nov 2023 05:10:23 +0900 Subject: [PATCH 015/185] =?UTF-8?q?feat:=20message=20delete=20swagger=20ap?= =?UTF-8?q?i=20=EB=93=B1=EB=A1=9D=20&=20entity=20typeORM=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/package-lock.json | 2971 +++++++++++++++-- back/package.json | 4 +- .../modules/message/dto/delete-message.dto.ts | 14 + .../modules/message/entity/message.entity.ts | 55 +- .../src/modules/message/message.controller.ts | 14 +- back/src/modules/message/message.service.ts | 4 + 6 files changed, 2834 insertions(+), 228 deletions(-) create mode 100644 back/src/modules/message/dto/delete-message.dto.ts diff --git a/back/package-lock.json b/back/package-lock.json index eccd8d9..1231aa9 100644 --- a/back/package-lock.json +++ b/back/package-lock.json @@ -20,7 +20,9 @@ "passport-google-oauth20": "^2.0.0", "passport-kakao": "^1.0.1", "reflect-metadata": "^0.1.13", - "rxjs": "^7.8.1" + "rxjs": "^7.8.1", + "sqlite3": "^5.1.6", + "typeorm": "^0.3.17" }, "devDependencies": { "@nestjs/cli": "^10.0.0", @@ -763,6 +765,17 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", + "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.22.15", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", @@ -841,7 +854,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -853,7 +866,7 @@ "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -937,6 +950,12 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "optional": true + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.13", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", @@ -1490,7 +1509,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6.0.0" } @@ -1518,7 +1537,7 @@ "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "devOptional": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.20", @@ -1538,6 +1557,80 @@ "node": ">=8" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@nestjs/cli": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.2.1.tgz", @@ -1759,6 +1852,77 @@ "node": ">= 8" } }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@nuxtjs/opencollective": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", @@ -1830,29 +1994,43 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@sqltools/formatter": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", + "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==" + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "optional": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true + "devOptional": true }, "node_modules/@types/babel__core": { "version": "7.20.3", @@ -2035,7 +2213,7 @@ "version": "20.8.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", - "dev": true, + "devOptional": true, "dependencies": { "undici-types": "~5.26.4" } @@ -2477,6 +2655,11 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -2493,7 +2676,7 @@ "version": "8.11.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "dev": true, + "devOptional": true, "bin": { "acorn": "bin/acorn" }, @@ -2523,11 +2706,47 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.4.0" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "optional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ajv": { "version": "8.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", @@ -2601,7 +2820,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -2620,6 +2838,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -2633,16 +2856,54 @@ "node": ">= 8" } }, + "node_modules/app-root-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", + "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/append-field": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "devOptional": true }, "node_modules/argparse": { "version": "2.0.1", @@ -2801,14 +3062,12 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -2927,7 +3186,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3061,44 +3319,150 @@ "node": ">= 0.8" } }, - "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "optional": true, "dependencies": { - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, + "node_modules/cacache/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, + "node_modules/cacache/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001559", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001559.tgz", - "integrity": "sha512-cPiMKZgqgkg5LY3/ntGeLFUpi6tzddBNS58A4tnTgQw1zON7u2sZMU7SzOeVH4tj20++9ggL+V6FDOFMTaFFYA==", - "dev": true, - "funding": [ - { + "node_modules/cacache/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, + "node_modules/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dependencies": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001559", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001559.tgz", + "integrity": "sha512-cPiMKZgqgkg5LY3/ntGeLFUpi6tzddBNS58A4tnTgQw1zON7u2sZMU7SzOeVH4tj20++9ggL+V6FDOFMTaFFYA==", + "dev": true, + "funding": [ + { "type": "opencollective", "url": "https://opencollective.com/browserslist" }, @@ -3169,6 +3533,14 @@ "fsevents": "~2.3.2" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, "node_modules/chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -3209,6 +3581,15 @@ "validator": "^13.7.0" } }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "optional": true, + "engines": { + "node": ">=6" + } + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -3221,6 +3602,77 @@ "node": ">=8" } }, + "node_modules/cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "dependencies": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "bin": { + "highlight": "bin/highlight" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/cli-highlight/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "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", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/cli-highlight/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cli-highlight/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, "node_modules/cli-spinners": { "version": "2.9.1", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", @@ -3261,7 +3713,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -3275,7 +3726,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -3329,6 +3779,14 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3375,8 +3833,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/concat-stream": { "version": "1.6.2", @@ -3397,6 +3854,11 @@ "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -3509,7 +3971,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "devOptional": true }, "node_modules/cross-spawn": { "version": "7.0.3", @@ -3525,11 +3987,25 @@ "node": ">= 8" } }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -3767,6 +4243,11 @@ "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -3784,6 +4265,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -3807,7 +4296,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.3.1" } @@ -3888,8 +4377,7 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/encodeurl": { "version": "1.0.2", @@ -3899,6 +4387,27 @@ "node": ">= 0.8" } }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -3921,6 +4430,21 @@ "node": ">=10.13.0" } }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "optional": true + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -3940,7 +4464,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, "engines": { "node": ">=6" } @@ -4688,6 +5211,33 @@ "node": ">=12" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/fs-monkey": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", @@ -4697,8 +5247,7 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/fsevents": { "version": "2.3.3", @@ -4722,6 +5271,30 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gauge/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -4735,7 +5308,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -4889,7 +5461,7 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "devOptional": true }, "node_modules/graphemer": { "version": "1.4.0", @@ -4947,6 +5519,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "node_modules/hasown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", @@ -4967,12 +5544,26 @@ "node": ">=8" } }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "engines": { + "node": "*" + } + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "optional": true + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -4988,6 +5579,32 @@ "node": ">= 0.8" } }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -4997,6 +5614,15 @@ "node": ">=10.17.0" } }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -5012,7 +5638,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, "funding": [ { "type": "github", @@ -5076,16 +5701,30 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "optional": true + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -5131,6 +5770,12 @@ "node": ">= 0.10" } }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "optional": true + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -5197,7 +5842,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -5250,6 +5894,12 @@ "node": ">=8" } }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "optional": true + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -5328,7 +5978,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "devOptional": true }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", @@ -6290,7 +6940,64 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "devOptional": true + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/make-fetch-happen/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true }, "node_modules/makeerror": { "version": "1.0.12", @@ -6405,7 +7112,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -6430,6 +7136,189 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-fetch/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-fetch/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -6444,8 +7333,7 @@ "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==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/multer": { "version": "1.4.4-lts.1", @@ -6470,6 +7358,16 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6496,6 +7394,11 @@ "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", "dev": true }, + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" + }, "node_modules/node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", @@ -6524,6 +7427,132 @@ } } }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp/node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/node-gyp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "optional": true + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -6536,6 +7565,20 @@ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", "dev": true }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -6557,6 +7600,17 @@ "node": ">=8" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/oauth": { "version": "0.9.15", "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", @@ -6593,7 +7647,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "dependencies": { "wrappy": "1" } @@ -6726,6 +7779,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -6765,6 +7833,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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/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/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/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -6874,7 +7960,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -7113,6 +8198,25 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -7292,6 +8396,11 @@ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" }, + "node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, "node_modules/repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", @@ -7305,7 +8414,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -7394,6 +8502,15 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "optional": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -7605,7 +8722,6 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -7620,7 +8736,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -7631,8 +8746,7 @@ "node_modules/semver/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/send": { "version": "0.18.0", @@ -7698,6 +8812,11 @@ "node": ">= 0.8.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "node_modules/set-function-length": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", @@ -7717,6 +8836,18 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -7815,6 +8946,44 @@ "node": ">=8" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "optional": true, + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", @@ -7849,6 +9018,58 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, + "node_modules/sqlite3": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.6.tgz", + "integrity": "sha512-olYkWoKFVNSSSQNvxVUfjiVbz3YtBwTJj+mfV5zpHmqW3sELx2Cf4QCdirMelhM5Zh+KDVaKgQHqCxrqiWHybw==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^4.2.0", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/ssri/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ssri/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -7916,7 +9137,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -7945,7 +9165,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -8099,6 +9318,46 @@ "node": ">=6" } }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/terser": { "version": "5.24.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", @@ -8226,6 +9485,25 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -8384,7 +9662,7 @@ "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, + "devOptional": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -8486,40 +9764,219 @@ "node": ">=4" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "node_modules/typeorm": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.17.tgz", + "integrity": "sha512-UDjUEwIQalO9tWw9O2A4GU+sT3oyoUXheHJy4ft+RFdnRdQctdQ34L9SqE2p7LdwzafHx1maxT+bqXON+Qnmig==", + "dependencies": { + "@sqltools/formatter": "^1.2.5", + "app-root-path": "^3.1.0", + "buffer": "^6.0.3", + "chalk": "^4.1.2", + "cli-highlight": "^2.1.11", + "date-fns": "^2.29.3", + "debug": "^4.3.4", + "dotenv": "^16.0.3", + "glob": "^8.1.0", + "mkdirp": "^2.1.3", + "reflect-metadata": "^0.1.13", + "sha.js": "^2.4.11", + "tslib": "^2.5.0", + "uuid": "^9.0.0", + "yargs": "^17.6.2" + }, + "bin": { + "typeorm": "cli.js", + "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js", + "typeorm-ts-node-esm": "cli-ts-node-esm.js" + }, + "engines": { + "node": ">= 12.9.0" + }, + "funding": { + "url": "https://opencollective.com/typeorm" + }, + "peerDependencies": { + "@google-cloud/spanner": "^5.18.0", + "@sap/hana-client": "^2.12.25", + "better-sqlite3": "^7.1.2 || ^8.0.0", + "hdb-pool": "^0.1.6", + "ioredis": "^5.0.4", + "mongodb": "^5.2.0", + "mssql": "^9.1.1", + "mysql2": "^2.2.5 || ^3.0.1", + "oracledb": "^5.1.0", + "pg": "^8.5.1", + "pg-native": "^3.0.0", + "pg-query-stream": "^4.0.0", + "redis": "^3.1.1 || ^4.0.0", + "sql.js": "^1.4.0", + "sqlite3": "^5.0.3", + "ts-node": "^10.7.0", + "typeorm-aurora-data-api-driver": "^2.0.0" + }, + "peerDependenciesMeta": { + "@google-cloud/spanner": { + "optional": true + }, + "@sap/hana-client": { + "optional": true + }, + "better-sqlite3": { + "optional": true + }, + "hdb-pool": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "mongodb": { + "optional": true + }, + "mssql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "oracledb": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "pg-query-stream": { + "optional": true + }, + "redis": { + "optional": true + }, + "sql.js": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "ts-node": { + "optional": true + }, + "typeorm-aurora-data-api-driver": { + "optional": true + } + } + }, + "node_modules/typeorm/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typeorm/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/typeorm/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/typeorm/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">=10" } }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + "node_modules/typeorm/node_modules/mkdirp": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", + "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/typescript": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -8548,7 +10005,25 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "devOptional": true + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } }, "node_modules/universalify": { "version": "2.0.1", @@ -8628,11 +10103,23 @@ "node": ">= 0.4.0" } }, + "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/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true + "devOptional": true }, "node_modules/v8-to-istanbul": { "version": "9.1.3", @@ -8800,7 +10287,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, + "devOptional": true, "dependencies": { "isexe": "^2.0.0" }, @@ -8811,6 +10298,14 @@ "node": ">= 8" } }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/windows-release": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-4.0.0.tgz", @@ -8914,8 +10409,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/write-file-atomic": { "version": "4.0.2", @@ -8948,7 +10442,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "engines": { "node": ">=10" } @@ -8963,7 +10456,6 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -8981,7 +10473,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "engines": { "node": ">=12" } @@ -8990,7 +10481,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6" } @@ -9541,6 +11032,14 @@ "@babel/helper-plugin-utils": "^7.22.5" } }, + "@babel/runtime": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", + "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", + "requires": { + "regenerator-runtime": "^0.14.0" + } + }, "@babel/template": { "version": "7.22.15", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", @@ -9606,7 +11105,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, + "devOptional": true, "requires": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -9615,7 +11114,7 @@ "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, + "devOptional": true, "requires": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -9681,6 +11180,12 @@ "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", "dev": true }, + "@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "optional": true + }, "@humanwhocodes/config-array": { "version": "0.11.13", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", @@ -10103,7 +11608,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true + "devOptional": true }, "@jridgewell/set-array": { "version": "1.1.2", @@ -10125,7 +11630,7 @@ "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "devOptional": true }, "@jridgewell/trace-mapping": { "version": "0.3.20", @@ -10142,6 +11647,60 @@ "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==" }, + "@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + } + } + }, "@nestjs/cli": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.2.1.tgz", @@ -10262,6 +11821,57 @@ "fastq": "^1.6.0" } }, + "@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "optional": true, + "requires": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "optional": true, + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "optional": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "@nuxtjs/opencollective": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", @@ -10317,29 +11927,40 @@ "@sinonjs/commons": "^3.0.0" } }, + "@sqltools/formatter": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", + "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==" + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "optional": true + }, "@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true + "devOptional": true }, "@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true + "devOptional": true }, "@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true + "devOptional": true }, "@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true + "devOptional": true }, "@types/babel__core": { "version": "7.20.3", @@ -10522,7 +12143,7 @@ "version": "20.8.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", - "dev": true, + "devOptional": true, "requires": { "undici-types": "~5.26.4" } @@ -10875,6 +12496,11 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -10888,7 +12514,7 @@ "version": "8.11.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "dev": true + "devOptional": true }, "acorn-import-assertions": { "version": "1.9.0", @@ -10908,7 +12534,34 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", - "dev": true + "devOptional": true + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, + "agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "optional": true, + "requires": { + "humanize-ms": "^1.2.1" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "optional": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } }, "ajv": { "version": "8.12.0", @@ -10957,8 +12610,7 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", @@ -10968,6 +12620,11 @@ "color-convert": "^2.0.1" } }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, "anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -10978,16 +12635,47 @@ "picomatch": "^2.0.4" } }, + "app-root-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", + "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==" + }, "append-field": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "devOptional": true }, "argparse": { "version": "2.0.1", @@ -11118,14 +12806,12 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "base64url": { "version": "3.0.1", @@ -11215,7 +12901,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -11297,6 +12982,87 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, + "cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "optional": true, + "requires": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + } + } + }, "call-bind": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", @@ -11362,6 +13128,11 @@ "readdirp": "~3.6.0" } }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, "chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -11390,13 +13161,73 @@ "validator": "^13.7.0" } }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "optional": true + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, "requires": { - "restore-cursor": "^3.1.0" + "restore-cursor": "^3.1.0" + } + }, + "cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "requires": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "dependencies": { + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + } } }, "cli-spinners": { @@ -11425,7 +13256,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -11436,7 +13266,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -11476,6 +13305,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -11513,8 +13347,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "concat-stream": { "version": "1.6.2", @@ -11532,6 +13365,11 @@ "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -11612,7 +13450,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "devOptional": true }, "cross-spawn": { "version": "7.0.3", @@ -11625,11 +13463,18 @@ "which": "^2.0.1" } }, + "date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "requires": { + "@babel/runtime": "^7.21.0" + } + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -11779,6 +13624,11 @@ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -11789,6 +13639,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==" + }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -11809,7 +13664,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true + "devOptional": true }, "diff-sequences": { "version": "29.6.3", @@ -11866,14 +13721,33 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -11893,6 +13767,18 @@ "tapable": "^2.2.0" } }, + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "optional": true + }, + "err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "optional": true + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -11911,8 +13797,7 @@ "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, "escape-html": { "version": "1.0.3", @@ -12484,6 +14369,29 @@ "universalify": "^2.0.0" } }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, "fs-monkey": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", @@ -12493,8 +14401,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "fsevents": { "version": "2.3.3", @@ -12508,6 +14415,29 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "dependencies": { + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + } + } + }, "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -12517,8 +14447,7 @@ "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { "version": "1.2.2", @@ -12626,7 +14555,7 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "devOptional": true }, "graphemer": { "version": "1.4.0", @@ -12663,6 +14592,11 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "hasown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", @@ -12677,12 +14611,23 @@ "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", "dev": true }, + "highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" + }, "html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "optional": true + }, "http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -12695,12 +14640,41 @@ "toidentifier": "1.0.1" } }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "optional": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "optional": true, + "requires": { + "ms": "^2.0.0" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -12712,8 +14686,7 @@ "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { "version": "5.2.4", @@ -12745,13 +14718,24 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true + "devOptional": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "optional": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "optional": true }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -12791,6 +14775,12 @@ "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true }, + "ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "optional": true + }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -12835,8 +14825,7 @@ "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-generator-fn": { "version": "2.1.0", @@ -12868,6 +14857,12 @@ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true }, + "is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "optional": true + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -12918,7 +14913,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "devOptional": true }, "istanbul-lib-coverage": { "version": "3.2.0", @@ -13659,7 +15654,57 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "devOptional": true + }, + "make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "optional": true, + "requires": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + } + } }, "makeerror": { "version": "1.0.12", @@ -13744,21 +15789,177 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, - "minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" - }, - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "optional": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + } + } + }, + "minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "optional": true, + "requires": { + "encoding": "^0.1.12", + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + } + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "optional": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + } + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "optional": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + } + } + }, + "minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "optional": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + } + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } }, "mkdirp": { "version": "0.5.6", @@ -13771,8 +15972,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "multer": { "version": "1.4.4-lts.1", @@ -13794,6 +15994,16 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -13817,6 +16027,11 @@ "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", "dev": true }, + "node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" + }, "node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", @@ -13834,6 +16049,104 @@ "whatwg-url": "^5.0.0" } }, + "node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "optional": true, + "requires": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "dependencies": { + "are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, + "gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "optional": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "optional": true, + "requires": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + } + }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "optional": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "optional": true + } + } + }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -13846,6 +16159,14 @@ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", "dev": true }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "requires": { + "abbrev": "1" + } + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -13861,6 +16182,17 @@ "path-key": "^3.0.0" } }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "oauth": { "version": "0.9.15", "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", @@ -13888,7 +16220,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "requires": { "wrappy": "1" } @@ -13979,6 +16310,15 @@ "p-limit": "^3.0.2" } }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "optional": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -14006,6 +16346,26 @@ "lines-and-columns": "^1.1.6" } }, + "parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + }, + "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==", + "requires": { + "parse5": "^6.0.1" + }, + "dependencies": { + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + } + } + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -14084,8 +16444,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, "path-key": { "version": "3.1.1", @@ -14255,6 +16614,22 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "optional": true + }, + "promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "optional": true, + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + } + }, "prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -14385,6 +16760,11 @@ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" }, + "regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", @@ -14394,8 +16774,7 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" }, "require-from-string": { "version": "2.0.2", @@ -14461,6 +16840,12 @@ } } }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "optional": true + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -14598,7 +16983,6 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, "requires": { "lru-cache": "^6.0.0" }, @@ -14607,7 +16991,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } @@ -14615,8 +16998,7 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -14682,6 +17064,11 @@ "send": "0.18.0" } }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "set-function-length": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", @@ -14698,6 +17085,15 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -14768,6 +17164,33 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "optional": true + }, + "socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "optional": true, + "requires": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + } + }, + "socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "optional": true, + "requires": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + } + }, "source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", @@ -14798,6 +17221,43 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, + "sqlite3": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.6.tgz", + "integrity": "sha512-olYkWoKFVNSSSQNvxVUfjiVbz3YtBwTJj+mfV5zpHmqW3sELx2Cf4QCdirMelhM5Zh+KDVaKgQHqCxrqiWHybw==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^4.2.0", + "node-gyp": "8.x", + "tar": "^6.1.11" + } + }, + "ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "optional": true, + "requires": { + "minipass": "^3.1.1" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + } + } + }, "stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -14854,7 +17314,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -14876,7 +17335,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "requires": { "ansi-regex": "^5.0.1" } @@ -14980,6 +17438,36 @@ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true }, + "tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, "terser": { "version": "5.24.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", @@ -15068,6 +17556,22 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -15166,7 +17670,7 @@ "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, + "devOptional": true, "requires": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -15253,11 +17757,77 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, + "typeorm": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.17.tgz", + "integrity": "sha512-UDjUEwIQalO9tWw9O2A4GU+sT3oyoUXheHJy4ft+RFdnRdQctdQ34L9SqE2p7LdwzafHx1maxT+bqXON+Qnmig==", + "requires": { + "@sqltools/formatter": "^1.2.5", + "app-root-path": "^3.1.0", + "buffer": "^6.0.3", + "chalk": "^4.1.2", + "cli-highlight": "^2.1.11", + "date-fns": "^2.29.3", + "debug": "^4.3.4", + "dotenv": "^16.0.3", + "glob": "^8.1.0", + "mkdirp": "^2.1.3", + "reflect-metadata": "^0.1.13", + "sha.js": "^2.4.11", + "tslib": "^2.5.0", + "uuid": "^9.0.0", + "yargs": "^17.6.2" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "mkdirp": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", + "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==" + } + } + }, "typescript": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", - "dev": true + "devOptional": true }, "uid": { "version": "2.0.2", @@ -15276,7 +17846,25 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "devOptional": true + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "optional": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "optional": true, + "requires": { + "imurmurhash": "^0.1.4" + } }, "universalify": { "version": "2.0.1", @@ -15324,11 +17912,16 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, + "uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" + }, "v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true + "devOptional": true }, "v8-to-istanbul": { "version": "9.1.3", @@ -15459,11 +18052,19 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, + "devOptional": true, "requires": { "isexe": "^2.0.0" } }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "windows-release": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-4.0.0.tgz", @@ -15538,8 +18139,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "write-file-atomic": { "version": "4.0.2", @@ -15567,8 +18167,7 @@ "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" }, "yallist": { "version": "3.1.1", @@ -15580,7 +18179,6 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, "requires": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -15594,14 +18192,13 @@ "yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" }, "yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true + "devOptional": true }, "yocto-queue": { "version": "0.1.0", diff --git a/back/package.json b/back/package.json index 1a730a0..13ecde9 100644 --- a/back/package.json +++ b/back/package.json @@ -31,7 +31,9 @@ "passport-google-oauth20": "^2.0.0", "passport-kakao": "^1.0.1", "reflect-metadata": "^0.1.13", - "rxjs": "^7.8.1" + "rxjs": "^7.8.1", + "sqlite3": "^5.1.6", + "typeorm": "^0.3.17" }, "devDependencies": { "@nestjs/cli": "^10.0.0", diff --git a/back/src/modules/message/dto/delete-message.dto.ts b/back/src/modules/message/dto/delete-message.dto.ts new file mode 100644 index 0000000..0ddd925 --- /dev/null +++ b/back/src/modules/message/dto/delete-message.dto.ts @@ -0,0 +1,14 @@ +import { IsNumber, IsNotEmpty } from 'class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class DeleteMessageDto { + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '메세지 id' }) + readonly message_id: number; + + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '스노우볼 id' }) + readonly snowball_id: number; +} diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 73219c9..5afbef1 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -1,46 +1,25 @@ -import { IsString, IsNumber, IsDateString, IsNotEmpty } from 'class-validator'; -import { ApiProperty } from '@nestjs/swagger'; +import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; -export class CreateMessageDto { - @IsString() - @IsNotEmpty() - @ApiProperty({ type: String, description: '메세지 내용' }) - readonly content: string; +@Entity() +export class MessageEntity { + @PrimaryGeneratedColumn() + snowball_id: number; - @IsNumber() - @IsNotEmpty() - @ApiProperty({ type: Number, description: '스노우볼 id' }) - readonly snowball_id: number; + @Column() + deco_id: number; - @IsDateString() - @ApiProperty({ - type: String, - description: '비공개 설정 시간, 공개 시 null로 설정' - }) - readonly private: string | null; + @Column() + content: string; - @IsNumber() - @IsNotEmpty() - @ApiProperty({ type: Number, description: '장식 id' }) - readonly deco_id: number; + @Column() + sender: string; - @IsString() - @IsNotEmpty() - @ApiProperty({ type: String, description: '익명 사용자 닉네임(From)' }) - readonly sender: string; + @Column({ nullable: true }) + private: string | null; - @IsDateString() - @ApiProperty({ - type: String, - description: '메세지 열람 시간, 비열람 시 null로 설정' - }) - readonly opened: string | null; + @Column({ nullable: true }) + opened: string | null; - @IsDateString() - @IsNotEmpty() - @ApiProperty({ - type: String, - description: '메세지 생성 시간' - }) - readonly created_at: string; + @Column() + created_at: string; } diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 03d0df8..399f6cb 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -1,6 +1,7 @@ -import { Controller, Post, Body } from '@nestjs/common'; +import { Controller, Post, Delete, Body } from '@nestjs/common'; import { MessageService } from './message.service'; import { CreateMessageDto } from './dto/create-message.dto'; +import { DeleteMessageDto } from './dto/delete-message.dto'; import { ApiResponse, ApiBody, ApiTags } from '@nestjs/swagger'; @ApiTags('Message API') @@ -8,7 +9,7 @@ import { ApiResponse, ApiBody, ApiTags } from '@nestjs/swagger'; export class MessageController { constructor(private readonly messageService: MessageService) {} - @Post('write') + @Post('create') @ApiResponse({ description: '메세지 생성 API' }) @@ -16,4 +17,13 @@ export class MessageController { createMessage(@Body() createMessageDto: CreateMessageDto) { return this.messageService.createMessage(createMessageDto); } + + @Delete('delete') + @ApiResponse({ + description: '메세지 삭제 API' + }) + @ApiBody({ type: DeleteMessageDto }) + deleteMessage(@Body() deleteMessageDto: DeleteMessageDto) { + return this.messageService.deleteMessage(deleteMessageDto); + } } diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index a72fc10..40c9e6d 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -1,9 +1,13 @@ import { Injectable } from '@nestjs/common'; import { CreateMessageDto } from './dto/create-message.dto'; +import { DeleteMessageDto } from './dto/delete-message.dto'; @Injectable() export class MessageService { createMessage(createMessageDto: CreateMessageDto) { return createMessageDto; } + deleteMessage(deleteMessageDto: DeleteMessageDto) { + return deleteMessageDto; + } } From 7af3ae048e653f3e27f5ee540c786a99a7b4652f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Sun, 12 Nov 2023 03:14:28 +0900 Subject: [PATCH 016/185] =?UTF-8?q?feat:=20share=20api=20=EC=84=A4?= =?UTF-8?q?=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/package-lock.json | 131 ++++++++++++++++++ back/package.json | 2 + back/src/app.module.ts | 3 +- .../src/modules/share/dto/create-share.dto.ts | 14 ++ .../modules/share/dto/restore-share.dto.ts | 9 ++ back/src/modules/share/share.controller.ts | 33 ++++- back/src/modules/share/share.service.ts | 20 ++- 7 files changed, 208 insertions(+), 4 deletions(-) create mode 100644 back/src/modules/share/dto/create-share.dto.ts create mode 100644 back/src/modules/share/dto/restore-share.dto.ts diff --git a/back/package-lock.json b/back/package-lock.json index 1231aa9..59d8c08 100644 --- a/back/package-lock.json +++ b/back/package-lock.json @@ -13,8 +13,10 @@ "@nestjs/core": "^10.0.0", "@nestjs/passport": "^10.0.2", "@nestjs/platform-express": "^10.0.0", + "@nestjs/typeorm": "^10.0.0", "class-validator": "^0.14.0", "dotenv": "^16.3.1", + "mysql": "^2.18.1", "passport": "^0.6.0", "passport-facebook": "^3.0.0", "passport-google-oauth20": "^2.0.0", @@ -1817,6 +1819,29 @@ } } }, + "node_modules/@nestjs/typeorm": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-10.0.0.tgz", + "integrity": "sha512-WQU4HCDTz4UavsFzvGUKDHqi0MO5K47yFoPXdmh+Z/hCNO7SHCMmV9jLiLukM8n5nKUqJ3jDqiljkWBcZPdCtA==", + "dependencies": { + "uuid": "9.0.0" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", + "reflect-metadata": "^0.1.13", + "rxjs": "^7.2.0", + "typeorm": "^0.3.0" + } + }, + "node_modules/@nestjs/typeorm/node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "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", @@ -3100,6 +3125,14 @@ "node": ">=0.6" } }, + "node_modules/bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -7358,6 +7391,39 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "node_modules/mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "dependencies": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mysql/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/mysql/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -9040,6 +9106,14 @@ } } }, + "node_modules/sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/ssri": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", @@ -11795,6 +11869,21 @@ "tslib": "2.6.2" } }, + "@nestjs/typeorm": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-10.0.0.tgz", + "integrity": "sha512-WQU4HCDTz4UavsFzvGUKDHqi0MO5K47yFoPXdmh+Z/hCNO7SHCMmV9jLiLukM8n5nKUqJ3jDqiljkWBcZPdCtA==", + "requires": { + "uuid": "9.0.0" + }, + "dependencies": { + "uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" + } + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -12824,6 +12913,11 @@ "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", "dev": true }, + "bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -15994,6 +16088,38 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "requires": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, "mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -17232,6 +17358,11 @@ "tar": "^6.1.11" } }, + "sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==" + }, "ssri": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", diff --git a/back/package.json b/back/package.json index 13ecde9..a69fe99 100644 --- a/back/package.json +++ b/back/package.json @@ -24,8 +24,10 @@ "@nestjs/core": "^10.0.0", "@nestjs/passport": "^10.0.2", "@nestjs/platform-express": "^10.0.0", + "@nestjs/typeorm": "^10.0.0", "class-validator": "^0.14.0", "dotenv": "^16.3.1", + "mysql": "^2.18.1", "passport": "^0.6.0", "passport-facebook": "^3.0.0", "passport-google-oauth20": "^2.0.0", diff --git a/back/src/app.module.ts b/back/src/app.module.ts index f3fdaf6..6f575f5 100644 --- a/back/src/app.module.ts +++ b/back/src/app.module.ts @@ -6,9 +6,10 @@ import { AuthModule } from './modules/auth/auth.module'; import { MessageController } from './modules/message/message.controller'; import { MessageModule } from './modules/message/message.module'; import { MessageService } from './modules/message/message.service'; +import { ShareModule } from './modules/share/share.module'; @Module({ - imports: [AuthModule, MessageModule], + imports: [ShareModule, AuthModule, MessageModule], controllers: [AppController, AuthController, MessageController], providers: [AppService, MessageService] }) diff --git a/back/src/modules/share/dto/create-share.dto.ts b/back/src/modules/share/dto/create-share.dto.ts new file mode 100644 index 0000000..2d51581 --- /dev/null +++ b/back/src/modules/share/dto/create-share.dto.ts @@ -0,0 +1,14 @@ +import { IsNumber, IsNotEmpty } from 'class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class CreateShareDto { + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '유저 id' }) + readonly user_id: number; + + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '스노우볼 id' }) + readonly snowball_id: number; +} diff --git a/back/src/modules/share/dto/restore-share.dto.ts b/back/src/modules/share/dto/restore-share.dto.ts new file mode 100644 index 0000000..3402e34 --- /dev/null +++ b/back/src/modules/share/dto/restore-share.dto.ts @@ -0,0 +1,9 @@ +import { IsString, IsNotEmpty } from 'class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class RestoreShareDto { + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '암호화된 링크' }) + readonly encrypted_link: string; +} diff --git a/back/src/modules/share/share.controller.ts b/back/src/modules/share/share.controller.ts index b304478..5eb61a0 100644 --- a/back/src/modules/share/share.controller.ts +++ b/back/src/modules/share/share.controller.ts @@ -1,4 +1,33 @@ -import { Controller } from '@nestjs/common'; +import { Controller, Post, Get, Body } from '@nestjs/common'; +import { ShareService } from './share.service'; +import { CreateShareDto } from './dto/create-share.dto'; +import { RestoreShareDto } from './dto/restore-share.dto'; +import { ApiResponse, ApiBody, ApiTags } from '@nestjs/swagger'; +@ApiTags('Share API') @Controller('share') -export class ShareController {} +export class ShareController { + constructor(private readonly shareService: ShareService) {} + + @Post('create') + @ApiResponse({ + description: '링크 생성 API' + }) + @ApiBody({ type: CreateShareDto }) + createShareLink(@Body() createShareDto: CreateShareDto) { + const encryptedLink = this.shareService.createShareLink(createShareDto); + return { encryptedLink }; + } + + @Get('restore') + @ApiResponse({ + description: '링크 복원 API' + }) + @ApiBody({ type: RestoreShareDto }) + restoreShareLink(@Body() restoreShareDto: RestoreShareDto) { + const decryptedLink = this.shareService.restoreShareLink( + restoreShareDto.encrypted_link + ); + return { decryptedLink }; + } +} diff --git a/back/src/modules/share/share.service.ts b/back/src/modules/share/share.service.ts index e55cb2d..f5f8bbb 100644 --- a/back/src/modules/share/share.service.ts +++ b/back/src/modules/share/share.service.ts @@ -1,4 +1,22 @@ import { Injectable } from '@nestjs/common'; +import * as crypto from 'crypto'; +import { CreateShareDto } from './dto/create-share.dto'; @Injectable() -export class ShareService {} +export class ShareService { + private readonly secretKey: string = 'secret_key'; // 암호화 키 + createShareLink(createShareDto: CreateShareDto): string { + const dataToEncrypt = `${createShareDto.user_id}-${createShareDto.snowball_id}`; + const cipher = crypto.createCipher('aes-256-cbc', this.secretKey); + let encryptedLink = cipher.update(dataToEncrypt, 'utf-8', 'hex'); + encryptedLink += cipher.final('hex'); + return encryptedLink; + } + + restoreShareLink(encryptedLink: string): string { + const decipher = crypto.createDecipher('aes-256-cbc', this.secretKey); + let decryptedLink = decipher.update(encryptedLink, 'hex', 'utf-8'); + decryptedLink += decipher.final('utf-8'); + return decryptedLink; + } +} From 41c62e4f4e4ad31f8d9e10d1b5257a8e6059b9f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Sun, 12 Nov 2023 03:21:56 +0900 Subject: [PATCH 017/185] =?UTF-8?q?fix:=20api=20=EB=AA=85=EC=84=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.controller.ts | 12 +++++++----- back/src/modules/share/share.controller.ts | 12 +++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 399f6cb..5b047dc 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -2,7 +2,7 @@ import { Controller, Post, Delete, Body } from '@nestjs/common'; import { MessageService } from './message.service'; import { CreateMessageDto } from './dto/create-message.dto'; import { DeleteMessageDto } from './dto/delete-message.dto'; -import { ApiResponse, ApiBody, ApiTags } from '@nestjs/swagger'; +import { ApiBody, ApiTags, ApiOperation } from '@nestjs/swagger'; @ApiTags('Message API') @Controller('message') @@ -10,8 +10,9 @@ export class MessageController { constructor(private readonly messageService: MessageService) {} @Post('create') - @ApiResponse({ - description: '메세지 생성 API' + @ApiOperation({ + summary: '메세지 생성 API', + description: '스노우볼에 메세지를 생성합니다.' }) @ApiBody({ type: CreateMessageDto }) createMessage(@Body() createMessageDto: CreateMessageDto) { @@ -19,8 +20,9 @@ export class MessageController { } @Delete('delete') - @ApiResponse({ - description: '메세지 삭제 API' + @ApiOperation({ + summary: '메세지 삭제 API', + description: '스노우볼에서 특정 메세지를 삭제합니다.' }) @ApiBody({ type: DeleteMessageDto }) deleteMessage(@Body() deleteMessageDto: DeleteMessageDto) { diff --git a/back/src/modules/share/share.controller.ts b/back/src/modules/share/share.controller.ts index 5eb61a0..683f51d 100644 --- a/back/src/modules/share/share.controller.ts +++ b/back/src/modules/share/share.controller.ts @@ -2,7 +2,7 @@ import { Controller, Post, Get, Body } from '@nestjs/common'; import { ShareService } from './share.service'; import { CreateShareDto } from './dto/create-share.dto'; import { RestoreShareDto } from './dto/restore-share.dto'; -import { ApiResponse, ApiBody, ApiTags } from '@nestjs/swagger'; +import { ApiOperation, ApiBody, ApiTags } from '@nestjs/swagger'; @ApiTags('Share API') @Controller('share') @@ -10,8 +10,9 @@ export class ShareController { constructor(private readonly shareService: ShareService) {} @Post('create') - @ApiResponse({ - description: '링크 생성 API' + @ApiOperation({ + summary: '링크 생성 API', + description: '암호화된 링크를 생성합니다.' }) @ApiBody({ type: CreateShareDto }) createShareLink(@Body() createShareDto: CreateShareDto) { @@ -20,8 +21,9 @@ export class ShareController { } @Get('restore') - @ApiResponse({ - description: '링크 복원 API' + @ApiOperation({ + summary: '링크 복원 API', + description: '암호화된 링크를 복원해 접속가능한 링크를 생성합니다.' }) @ApiBody({ type: RestoreShareDto }) restoreShareLink(@Body() restoreShareDto: RestoreShareDto) { From 700e337c2d81cbd7af407060990cdef3eec94100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Sun, 12 Nov 2023 06:42:52 +0900 Subject: [PATCH 018/185] =?UTF-8?q?feat:=20typeorm=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20message=20entity=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/package-lock.json | 174 ++++++++++++++++++ back/package.json | 1 + back/src/app.module.ts | 15 +- back/src/config/ormconfig.ts | 15 ++ back/src/main.ts | 2 - .../modules/message/entity/message.entity.ts | 3 + .../src/modules/message/message.controller.ts | 2 +- back/src/modules/message/message.module.ts | 3 + back/src/modules/message/message.service.ts | 22 ++- back/tsconfig.json | 3 +- 10 files changed, 227 insertions(+), 13 deletions(-) create mode 100644 back/src/config/ormconfig.ts diff --git a/back/package-lock.json b/back/package-lock.json index 59d8c08..e704c52 100644 --- a/back/package-lock.json +++ b/back/package-lock.json @@ -17,6 +17,7 @@ "class-validator": "^0.14.0", "dotenv": "^16.3.1", "mysql": "^2.18.1", + "mysql2": "^3.6.3", "passport": "^0.6.0", "passport-facebook": "^3.0.0", "passport-google-oauth20": "^2.0.0", @@ -4281,6 +4282,14 @@ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "engines": { + "node": ">=0.10" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -5328,6 +5337,14 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dependencies": { + "is-property": "^1.0.2" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -5951,6 +5968,11 @@ "node": ">=8" } }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -6921,6 +6943,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -7424,6 +7451,51 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/mysql2": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.6.3.tgz", + "integrity": "sha512-qYd/1CDuW1KYZjD4tzg2O8YS3X/UWuGH8ZMHyMeggMTXL3yOdMisbwZ5SNkHzDGlZXKYLAvV8tMrEH+NUMz3fw==", + "dependencies": { + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^5.2.1", + "lru-cache": "^8.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/mysql2/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mysql2/node_modules/lru-cache": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", + "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==", + "engines": { + "node": ">=16.14" + } + }, + "node_modules/mysql2/node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -7434,6 +7506,25 @@ "thenify-all": "^1.0.0" } }, + "node_modules/named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "dependencies": { + "lru-cache": "^7.14.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -8855,6 +8946,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, "node_modules/serialize-javascript": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", @@ -13723,6 +13819,11 @@ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" }, + "denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -14532,6 +14633,14 @@ } } }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "requires": { + "is-property": "^1.0.2" + } + }, "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -14969,6 +15078,11 @@ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + }, "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -15711,6 +15825,11 @@ "is-unicode-supported": "^0.1.0" } }, + "long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -16120,6 +16239,41 @@ } } }, + "mysql2": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.6.3.tgz", + "integrity": "sha512-qYd/1CDuW1KYZjD4tzg2O8YS3X/UWuGH8ZMHyMeggMTXL3yOdMisbwZ5SNkHzDGlZXKYLAvV8tMrEH+NUMz3fw==", + "requires": { + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^5.2.1", + "lru-cache": "^8.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "lru-cache": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", + "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==" + }, + "sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==" + } + } + }, "mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -16130,6 +16284,21 @@ "thenify-all": "^1.0.0" } }, + "named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "requires": { + "lru-cache": "^7.14.1" + }, + "dependencies": { + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" + } + } + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -17170,6 +17339,11 @@ } } }, + "seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, "serialize-javascript": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", diff --git a/back/package.json b/back/package.json index a69fe99..16b6d9d 100644 --- a/back/package.json +++ b/back/package.json @@ -28,6 +28,7 @@ "class-validator": "^0.14.0", "dotenv": "^16.3.1", "mysql": "^2.18.1", + "mysql2": "^3.6.3", "passport": "^0.6.0", "passport-facebook": "^3.0.0", "passport-google-oauth20": "^2.0.0", diff --git a/back/src/app.module.ts b/back/src/app.module.ts index 6f575f5..2106c23 100644 --- a/back/src/app.module.ts +++ b/back/src/app.module.ts @@ -1,16 +1,21 @@ import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { AuthController } from './modules/auth/auth.controller'; import { AuthModule } from './modules/auth/auth.module'; -import { MessageController } from './modules/message/message.controller'; import { MessageModule } from './modules/message/message.module'; -import { MessageService } from './modules/message/message.service'; import { ShareModule } from './modules/share/share.module'; +import typeOrmConfig from './config/ormconfig'; @Module({ - imports: [ShareModule, AuthModule, MessageModule], - controllers: [AppController, AuthController, MessageController], - providers: [AppService, MessageService] + imports: [ + TypeOrmModule.forRoot(typeOrmConfig), + ShareModule, + AuthModule, + MessageModule + ], + controllers: [AppController, AuthController], + providers: [AppService] }) export class AppModule {} diff --git a/back/src/config/ormconfig.ts b/back/src/config/ormconfig.ts new file mode 100644 index 0000000..a61ec16 --- /dev/null +++ b/back/src/config/ormconfig.ts @@ -0,0 +1,15 @@ +import { TypeOrmModuleOptions } from '@nestjs/typeorm'; +import * as dotenv from 'dotenv'; +dotenv.config(); + +const typeOrmConfig: TypeOrmModuleOptions = { + type: 'mysql', + host: process.env.DATABASE_HOST, + username: process.env.DATABASE_USER, + port: Number(process.env.DATABASE_PORT), + password: process.env.DATABASE_PASSWORD, + database: process.env.DATABASE_SCHEMA, + entities: [process.env.ENTITY_PATH], + synchronize: true +}; +export default typeOrmConfig; diff --git a/back/src/main.ts b/back/src/main.ts index e003b2a..deca767 100644 --- a/back/src/main.ts +++ b/back/src/main.ts @@ -1,10 +1,8 @@ import { NestFactory } from '@nestjs/core'; import { setupSwagger } from 'src/util/swagger'; import { AppModule } from './app.module'; -import * as dotenv from 'dotenv'; async function bootstrap() { - dotenv.config(); const app = await NestFactory.create(AppModule); setupSwagger(app); await app.listen(3000); diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 5afbef1..a6b90d9 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -3,6 +3,9 @@ import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; @Entity() export class MessageEntity { @PrimaryGeneratedColumn() + id: number; + + @Column() snowball_id: number; @Column() diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 5b047dc..585f2e1 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -26,6 +26,6 @@ export class MessageController { }) @ApiBody({ type: DeleteMessageDto }) deleteMessage(@Body() deleteMessageDto: DeleteMessageDto) { - return this.messageService.deleteMessage(deleteMessageDto); + this.messageService.deleteMessage(deleteMessageDto); } } diff --git a/back/src/modules/message/message.module.ts b/back/src/modules/message/message.module.ts index f6d7999..f850ab2 100644 --- a/back/src/modules/message/message.module.ts +++ b/back/src/modules/message/message.module.ts @@ -1,8 +1,11 @@ import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; import { MessageController } from './message.controller'; import { MessageService } from './message.service'; +import { MessageEntity } from './entity/message.entity'; @Module({ + imports: [TypeOrmModule.forFeature([MessageEntity])], controllers: [MessageController], providers: [MessageService] }) diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 40c9e6d..f7c4db4 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -1,13 +1,27 @@ import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; import { CreateMessageDto } from './dto/create-message.dto'; import { DeleteMessageDto } from './dto/delete-message.dto'; +import { MessageEntity } from './entity/message.entity'; @Injectable() export class MessageService { - createMessage(createMessageDto: CreateMessageDto) { - return createMessageDto; + constructor( + @InjectRepository(MessageEntity) + private readonly messageRepository: Repository + ) {} + async createMessage( + createMessageDto: CreateMessageDto + ): Promise { + const message = this.messageRepository.create(createMessageDto); + return await this.messageRepository.save(message); } - deleteMessage(deleteMessageDto: DeleteMessageDto) { - return deleteMessageDto; + async deleteMessage(deleteMessageDto: DeleteMessageDto): Promise { + await this.messageRepository.delete(deleteMessageDto.message_id); + } + + async findAllMessage(): Promise { + return await this.messageRepository.find(); } } diff --git a/back/tsconfig.json b/back/tsconfig.json index 95f5641..5485d9d 100644 --- a/back/tsconfig.json +++ b/back/tsconfig.json @@ -16,6 +16,7 @@ "noImplicitAny": false, "strictBindCallApply": false, "forceConsistentCasingInFileNames": false, - "noFallthroughCasesInSwitch": false + "noFallthroughCasesInSwitch": false, + "esModuleInterop": true } } From 01789eb523bd0998093d92a86151bccb9eadaad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Sun, 12 Nov 2023 06:50:37 +0900 Subject: [PATCH 019/185] =?UTF-8?q?fix:=20typeorm=20ER=5FNOT=5FSUPPORTED?= =?UTF-8?q?=5FAUTH=5FMODE=20=EC=97=90=EB=9F=AC=20=ED=94=BD=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/package-lock.json | 92 ------------------------------------------ back/package.json | 1 - 2 files changed, 93 deletions(-) diff --git a/back/package-lock.json b/back/package-lock.json index e704c52..12ca620 100644 --- a/back/package-lock.json +++ b/back/package-lock.json @@ -16,7 +16,6 @@ "@nestjs/typeorm": "^10.0.0", "class-validator": "^0.14.0", "dotenv": "^16.3.1", - "mysql": "^2.18.1", "mysql2": "^3.6.3", "passport": "^0.6.0", "passport-facebook": "^3.0.0", @@ -3126,14 +3125,6 @@ "node": ">=0.6" } }, - "node_modules/bignumber.js": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", - "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", - "engines": { - "node": "*" - } - }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -7418,39 +7409,6 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, - "node_modules/mysql": { - "version": "2.18.1", - "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", - "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", - "dependencies": { - "bignumber.js": "9.0.0", - "readable-stream": "2.3.7", - "safe-buffer": "5.1.2", - "sqlstring": "2.3.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mysql/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/mysql/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, "node_modules/mysql2": { "version": "3.6.3", "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.6.3.tgz", @@ -9202,14 +9160,6 @@ } } }, - "node_modules/sqlstring": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", - "integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/ssri": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", @@ -13009,11 +12959,6 @@ "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", "dev": true }, - "bignumber.js": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", - "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" - }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -16207,38 +16152,6 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, - "mysql": { - "version": "2.18.1", - "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", - "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", - "requires": { - "bignumber.js": "9.0.0", - "readable-stream": "2.3.7", - "safe-buffer": "5.1.2", - "sqlstring": "2.3.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, "mysql2": { "version": "3.6.3", "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.6.3.tgz", @@ -17532,11 +17445,6 @@ "tar": "^6.1.11" } }, - "sqlstring": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", - "integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==" - }, "ssri": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", diff --git a/back/package.json b/back/package.json index 16b6d9d..4ae4c3d 100644 --- a/back/package.json +++ b/back/package.json @@ -27,7 +27,6 @@ "@nestjs/typeorm": "^10.0.0", "class-validator": "^0.14.0", "dotenv": "^16.3.1", - "mysql": "^2.18.1", "mysql2": "^3.6.3", "passport": "^0.6.0", "passport-facebook": "^3.0.0", From b71c4605ec87dea7dfb0464df04af9179437384d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 14 Nov 2023 04:48:55 +0900 Subject: [PATCH 020/185] =?UTF-8?q?feat:=20=EC=84=9C=EB=B2=84=20test?= =?UTF-8?q?=EC=9A=A9=20=ED=94=84=EB=A1=9C=EC=A0=9D=ED=8A=B8=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test | 1 + 1 file changed, 1 insertion(+) create mode 160000 test diff --git a/test b/test new file mode 160000 index 0000000..38a4089 --- /dev/null +++ b/test @@ -0,0 +1 @@ +Subproject commit 38a4089437755bfca532f4eba4a83ae5a5c443d9 From d903bd9a352f6d30d0f979fb16e7ec89beaf9aa8 Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 16 Nov 2023 18:24:44 +0900 Subject: [PATCH 021/185] =?UTF-8?q?feat:=20swagger=20api=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/package-lock.json | 153 ++++++++++++++++-- back/package.json | 5 +- back/src/app.module.ts | 10 +- .../modules/message/dto/create-message.dto.ts | 24 +-- .../modules/message/dto/delete-message.dto.ts | 7 +- .../modules/message/entity/message.entity.ts | 22 +-- .../src/modules/message/message.controller.ts | 12 +- back/src/modules/message/message.service.ts | 10 +- .../src/modules/share/dto/create-share.dto.ts | 14 -- .../modules/share/dto/restore-share.dto.ts | 9 -- back/src/modules/share/share.controller.ts | 35 ---- back/src/modules/share/share.module.ts | 9 -- back/src/modules/share/share.service.ts | 22 --- .../snowball/dto/create-snowball.dto.ts | 45 ++++++ .../snowball/dto/decoration-snowball.dto.ts | 14 ++ .../snowball/dto/update-snowball.dto.ts | 35 ++++ .../snowball/entity/snowball.entity.ts | 22 +++ .../modules/snowball/snowball.controller.ts | 31 +++- back/src/modules/snowball/snowball.module.ts | 4 + back/src/modules/snowball/snowball.service.ts | 21 ++- package-lock.json | 6 + 21 files changed, 361 insertions(+), 149 deletions(-) delete mode 100644 back/src/modules/share/dto/create-share.dto.ts delete mode 100644 back/src/modules/share/dto/restore-share.dto.ts delete mode 100644 back/src/modules/share/share.controller.ts delete mode 100644 back/src/modules/share/share.module.ts delete mode 100644 back/src/modules/share/share.service.ts create mode 100644 back/src/modules/snowball/dto/create-snowball.dto.ts create mode 100644 back/src/modules/snowball/dto/decoration-snowball.dto.ts create mode 100644 back/src/modules/snowball/dto/update-snowball.dto.ts create mode 100644 back/src/modules/snowball/entity/snowball.entity.ts create mode 100644 package-lock.json diff --git a/back/package-lock.json b/back/package-lock.json index 12ca620..9dfb1f0 100644 --- a/back/package-lock.json +++ b/back/package-lock.json @@ -9,18 +9,21 @@ "version": "0.0.1", "license": "UNLICENSED", "dependencies": { + "@nestjs/class-transformer": "^0.4.0", + "@nestjs/class-validator": "^0.13.4", "@nestjs/common": "^10.0.0", "@nestjs/core": "^10.0.0", "@nestjs/passport": "^10.0.2", "@nestjs/platform-express": "^10.0.0", + "@nestjs/swagger": "^7.1.16", "@nestjs/typeorm": "^10.0.0", - "class-validator": "^0.14.0", "dotenv": "^16.3.1", "mysql2": "^3.6.3", "passport": "^0.6.0", "passport-facebook": "^3.0.0", "passport-google-oauth20": "^2.0.0", "passport-kakao": "^1.0.1", + "passport-naver-v2": "^2.0.8", "reflect-metadata": "^0.1.13", "rxjs": "^7.8.1", "sqlite3": "^5.1.6", @@ -1633,6 +1636,20 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@nestjs/class-transformer": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@nestjs/class-transformer/-/class-transformer-0.4.0.tgz", + "integrity": "sha512-aHKhqPVixFCo8m7n2iP1uGgfyF0eYlAgGJKfW27l0BvRCTPBjmoL4956Cf9xVu6WNJzVsp//SOcpIavdnNHYZg==" + }, + "node_modules/@nestjs/class-validator": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/@nestjs/class-validator/-/class-validator-0.13.4.tgz", + "integrity": "sha512-/mqZL36LJ5uV5WDhi87Cd52IssuO+SStaOr2+6sBsvCCGUWkoJes4Wwzmm3m/gdHH+tsNxX60sVSzYcU6hAy9Q==", + "dependencies": { + "libphonenumber-js": "^1.9.43", + "validator": "^13.7.0" + } + }, "node_modules/@nestjs/cli": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.2.1.tgz", @@ -1747,6 +1764,25 @@ } } }, + "node_modules/@nestjs/mapped-types": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.3.tgz", + "integrity": "sha512-40Zdqg98lqoF0+7ThWIZFStxgzisK6GG22+1ABO4kZiGF/Tu2FE+DYLw+Q9D94vcFWizJ+MSjNN4ns9r6hIGxw==", + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "class-transformer": "^0.4.0 || ^0.5.0", + "class-validator": "^0.13.0 || ^0.14.0", + "reflect-metadata": "^0.1.12" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, "node_modules/@nestjs/passport": { "version": "10.0.2", "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-10.0.2.tgz", @@ -1792,6 +1828,37 @@ "typescript": ">=4.8.2" } }, + "node_modules/@nestjs/swagger": { + "version": "7.1.16", + "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.1.16.tgz", + "integrity": "sha512-f9KBk/BX9MUKPTj7tQNYJ124wV/jP5W2lwWHLGwe/4qQXixuDOo39zP55HIJ44LE7S04B7BOeUOo9GBJD/vRcw==", + "dependencies": { + "@nestjs/mapped-types": "2.0.3", + "js-yaml": "4.1.0", + "lodash": "4.17.21", + "path-to-regexp": "3.2.0", + "swagger-ui-dist": "5.9.1" + }, + "peerDependencies": { + "@fastify/static": "^6.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" + }, + "peerDependenciesMeta": { + "@fastify/static": { + "optional": true + }, + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, "node_modules/@nestjs/testing": { "version": "10.2.8", "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.2.8.tgz", @@ -2310,7 +2377,9 @@ "node_modules/@types/validator": { "version": "13.11.6", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.6.tgz", - "integrity": "sha512-HUgHujPhKuNzgNXBRZKYexwoG+gHKU+tnfPqjWXFghZAnn73JElicMkuSKJyLGr9JgyA8IgK7fj88IyA9rwYeQ==" + "integrity": "sha512-HUgHujPhKuNzgNXBRZKYexwoG+gHKU+tnfPqjWXFghZAnn73JElicMkuSKJyLGr9JgyA8IgK7fj88IyA9rwYeQ==", + "optional": true, + "peer": true }, "node_modules/@types/yargs": { "version": "17.0.29", @@ -2933,8 +3002,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-flatten": { "version": "1.1.1", @@ -3600,6 +3668,8 @@ "version": "0.14.0", "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz", "integrity": "sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==", + "optional": true, + "peer": true, "dependencies": { "@types/validator": "^13.7.10", "libphonenumber-js": "^1.10.14", @@ -6751,7 +6821,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" }, @@ -6903,8 +6972,7 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "node_modules/lodash.memoize": { "version": "4.1.2", @@ -8035,6 +8103,14 @@ "node": ">= 0.4.0" } }, + "node_modules/passport-naver-v2": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/passport-naver-v2/-/passport-naver-v2-2.0.8.tgz", + "integrity": "sha512-CA0u+aA4K4Zf5e3dSd47agOS69ULOdBGei7CZY2BN1cEbLnhnc6OalFPvnXLuEKT8I4IuGwvh3EBZCST2FoI+A==", + "dependencies": { + "passport-oauth2": "^1.5.0" + } + }, "node_modules/passport-oauth2": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.7.0.tgz", @@ -9404,6 +9480,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/swagger-ui-dist": { + "version": "5.9.1", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.9.1.tgz", + "integrity": "sha512-5zAx+hUwJb9T3EAntc7TqYkV716CMqG6sZpNlAAMOMWkNXRYxGkN8ADIvD55dQZ10LxN90ZM/TQmN7y1gpICnw==" + }, "node_modules/symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", @@ -11821,6 +11902,20 @@ } } }, + "@nestjs/class-transformer": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@nestjs/class-transformer/-/class-transformer-0.4.0.tgz", + "integrity": "sha512-aHKhqPVixFCo8m7n2iP1uGgfyF0eYlAgGJKfW27l0BvRCTPBjmoL4956Cf9xVu6WNJzVsp//SOcpIavdnNHYZg==" + }, + "@nestjs/class-validator": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/@nestjs/class-validator/-/class-validator-0.13.4.tgz", + "integrity": "sha512-/mqZL36LJ5uV5WDhi87Cd52IssuO+SStaOr2+6sBsvCCGUWkoJes4Wwzmm3m/gdHH+tsNxX60sVSzYcU6hAy9Q==", + "requires": { + "libphonenumber-js": "^1.9.43", + "validator": "^13.7.0" + } + }, "@nestjs/cli": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.2.1.tgz", @@ -11875,6 +11970,12 @@ "uid": "2.0.2" } }, + "@nestjs/mapped-types": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.3.tgz", + "integrity": "sha512-40Zdqg98lqoF0+7ThWIZFStxgzisK6GG22+1ABO4kZiGF/Tu2FE+DYLw+Q9D94vcFWizJ+MSjNN4ns9r6hIGxw==", + "requires": {} + }, "@nestjs/passport": { "version": "10.0.2", "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-10.0.2.tgz", @@ -11906,6 +12007,18 @@ "pluralize": "8.0.0" } }, + "@nestjs/swagger": { + "version": "7.1.16", + "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.1.16.tgz", + "integrity": "sha512-f9KBk/BX9MUKPTj7tQNYJ124wV/jP5W2lwWHLGwe/4qQXixuDOo39zP55HIJ44LE7S04B7BOeUOo9GBJD/vRcw==", + "requires": { + "@nestjs/mapped-types": "2.0.3", + "js-yaml": "4.1.0", + "lodash": "4.17.21", + "path-to-regexp": "3.2.0", + "swagger-ui-dist": "5.9.1" + } + }, "@nestjs/testing": { "version": "10.2.8", "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.2.8.tgz", @@ -12350,7 +12463,9 @@ "@types/validator": { "version": "13.11.6", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.6.tgz", - "integrity": "sha512-HUgHujPhKuNzgNXBRZKYexwoG+gHKU+tnfPqjWXFghZAnn73JElicMkuSKJyLGr9JgyA8IgK7fj88IyA9rwYeQ==" + "integrity": "sha512-HUgHujPhKuNzgNXBRZKYexwoG+gHKU+tnfPqjWXFghZAnn73JElicMkuSKJyLGr9JgyA8IgK7fj88IyA9rwYeQ==", + "optional": true, + "peer": true }, "@types/yargs": { "version": "17.0.29", @@ -12815,8 +12930,7 @@ "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==" }, "array-flatten": { "version": "1.1.1", @@ -13290,6 +13404,8 @@ "version": "0.14.0", "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz", "integrity": "sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==", + "optional": true, + "peer": true, "requires": { "@types/validator": "^13.7.10", "libphonenumber-js": "^1.10.14", @@ -15628,7 +15744,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "requires": { "argparse": "^2.0.1" } @@ -15745,8 +15860,7 @@ "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "lodash.memoize": { "version": "4.1.2", @@ -16626,6 +16740,14 @@ } } }, + "passport-naver-v2": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/passport-naver-v2/-/passport-naver-v2-2.0.8.tgz", + "integrity": "sha512-CA0u+aA4K4Zf5e3dSd47agOS69ULOdBGei7CZY2BN1cEbLnhnc6OalFPvnXLuEKT8I4IuGwvh3EBZCST2FoI+A==", + "requires": { + "passport-oauth2": "^1.5.0" + } + }, "passport-oauth2": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.7.0.tgz", @@ -17629,6 +17751,11 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, + "swagger-ui-dist": { + "version": "5.9.1", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.9.1.tgz", + "integrity": "sha512-5zAx+hUwJb9T3EAntc7TqYkV716CMqG6sZpNlAAMOMWkNXRYxGkN8ADIvD55dQZ10LxN90ZM/TQmN7y1gpICnw==" + }, "symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", diff --git a/back/package.json b/back/package.json index 4ae4c3d..54d00cf 100644 --- a/back/package.json +++ b/back/package.json @@ -20,18 +20,21 @@ "test:e2e": "jest --config ./test/jest-e2e.json" }, "dependencies": { + "@nestjs/class-transformer": "^0.4.0", + "@nestjs/class-validator": "^0.13.4", "@nestjs/common": "^10.0.0", "@nestjs/core": "^10.0.0", "@nestjs/passport": "^10.0.2", "@nestjs/platform-express": "^10.0.0", + "@nestjs/swagger": "^7.1.16", "@nestjs/typeorm": "^10.0.0", - "class-validator": "^0.14.0", "dotenv": "^16.3.1", "mysql2": "^3.6.3", "passport": "^0.6.0", "passport-facebook": "^3.0.0", "passport-google-oauth20": "^2.0.0", "passport-kakao": "^1.0.1", + "passport-naver-v2": "^2.0.8", "reflect-metadata": "^0.1.13", "rxjs": "^7.8.1", "sqlite3": "^5.1.6", diff --git a/back/src/app.module.ts b/back/src/app.module.ts index 2106c23..2dfd366 100644 --- a/back/src/app.module.ts +++ b/back/src/app.module.ts @@ -4,17 +4,11 @@ import { AppController } from './app.controller'; import { AppService } from './app.service'; import { AuthController } from './modules/auth/auth.controller'; import { AuthModule } from './modules/auth/auth.module'; -import { MessageModule } from './modules/message/message.module'; -import { ShareModule } from './modules/share/share.module'; +import { SnowballModule } from './modules/snowball/snowball.module'; import typeOrmConfig from './config/ormconfig'; @Module({ - imports: [ - TypeOrmModule.forRoot(typeOrmConfig), - ShareModule, - AuthModule, - MessageModule - ], + imports: [TypeOrmModule.forRoot(typeOrmConfig), AuthModule, SnowballModule], controllers: [AppController, AuthController], providers: [AppService] }) diff --git a/back/src/modules/message/dto/create-message.dto.ts b/back/src/modules/message/dto/create-message.dto.ts index 98ff184..8ca2735 100644 --- a/back/src/modules/message/dto/create-message.dto.ts +++ b/back/src/modules/message/dto/create-message.dto.ts @@ -1,24 +1,24 @@ -import { IsString, IsNumber, IsNotEmpty } from 'class-validator'; +import { IsString, IsNotEmpty, IsNumber } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class CreateMessageDto { + @IsNotEmpty() + @IsString() + @ApiProperty({ type: String, description: '스노우볼 uuid' }) + readonly snowball_id: string; + @IsString() @IsNotEmpty() - @ApiProperty({ type: String, description: '메세지 내용' }) - readonly content: string; + @ApiProperty({ type: String, description: '익명 사용자 닉네임(From)' }) + readonly sender: string; - @IsNumber() + @IsString() @IsNotEmpty() - @ApiProperty({ type: Number, description: '스노우볼 id' }) - readonly snowball_id: number; + @ApiProperty({ type: String, description: '메세지 내용' }) + readonly content: string; @IsNumber() @IsNotEmpty() - @ApiProperty({ type: Number, description: '장식 id' }) + @ApiProperty({ type: Number, description: '데코오브젝트 id' }) readonly deco_id: number; - - @IsString() - @IsNotEmpty() - @ApiProperty({ type: String, description: '익명 사용자 닉네임(From)' }) - readonly sender: string; } diff --git a/back/src/modules/message/dto/delete-message.dto.ts b/back/src/modules/message/dto/delete-message.dto.ts index 0ddd925..62b48aa 100644 --- a/back/src/modules/message/dto/delete-message.dto.ts +++ b/back/src/modules/message/dto/delete-message.dto.ts @@ -1,4 +1,4 @@ -import { IsNumber, IsNotEmpty } from 'class-validator'; +import { IsNumber, IsNotEmpty } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class DeleteMessageDto { @@ -6,9 +6,4 @@ export class DeleteMessageDto { @IsNotEmpty() @ApiProperty({ type: Number, description: '메세지 id' }) readonly message_id: number; - - @IsNumber() - @IsNotEmpty() - @ApiProperty({ type: Number, description: '스노우볼 id' }) - readonly snowball_id: number; } diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index a6b90d9..bd5c2bc 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -1,12 +1,17 @@ -import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; - -@Entity() +import { + Entity, + Column, + PrimaryGeneratedColumn, + CreateDateColumn +} from 'typeorm'; + +@Entity({ name: 'message' }) export class MessageEntity { @PrimaryGeneratedColumn() id: number; @Column() - snowball_id: number; + snowball_id: string; @Column() deco_id: number; @@ -17,12 +22,9 @@ export class MessageEntity { @Column() sender: string; - @Column({ nullable: true }) - private: string | null; - - @Column({ nullable: true }) + @Column({ nullable: true, default: null }) opened: string | null; - @Column() - created_at: string; + @CreateDateColumn() + created_at: Date; } diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 585f2e1..ae491b5 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -1,31 +1,33 @@ -import { Controller, Post, Delete, Body } from '@nestjs/common'; +import { Controller, Post, Delete, Body, Param } from '@nestjs/common'; import { MessageService } from './message.service'; import { CreateMessageDto } from './dto/create-message.dto'; import { DeleteMessageDto } from './dto/delete-message.dto'; -import { ApiBody, ApiTags, ApiOperation } from '@nestjs/swagger'; +import { ApiBody, ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; @ApiTags('Message API') @Controller('message') export class MessageController { constructor(private readonly messageService: MessageService) {} - @Post('create') + @Post() @ApiOperation({ summary: '메세지 생성 API', description: '스노우볼에 메세지를 생성합니다.' }) @ApiBody({ type: CreateMessageDto }) + @ApiResponse({ status: 201, description: 'Created' }) createMessage(@Body() createMessageDto: CreateMessageDto) { return this.messageService.createMessage(createMessageDto); } - @Delete('delete') + @Delete(':message_id') @ApiOperation({ summary: '메세지 삭제 API', description: '스노우볼에서 특정 메세지를 삭제합니다.' }) @ApiBody({ type: DeleteMessageDto }) - deleteMessage(@Body() deleteMessageDto: DeleteMessageDto) { + @ApiResponse({ status: 204, description: 'No Content' }) + deleteMessage(@Param() deleteMessageDto: DeleteMessageDto) { this.messageService.deleteMessage(deleteMessageDto); } } diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index f7c4db4..dc0709e 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -14,8 +14,14 @@ export class MessageService { async createMessage( createMessageDto: CreateMessageDto ): Promise { - const message = this.messageRepository.create(createMessageDto); - return await this.messageRepository.save(message); + const messageEntity = this.messageRepository.create({ + snowball_id: createMessageDto.snowball_id, + deco_id: createMessageDto.deco_id, + content: createMessageDto.content, + sender: createMessageDto.sender + // opened와 created_at은 자동으로 설정됩니다. + }); + return await this.messageRepository.save(messageEntity); } async deleteMessage(deleteMessageDto: DeleteMessageDto): Promise { await this.messageRepository.delete(deleteMessageDto.message_id); diff --git a/back/src/modules/share/dto/create-share.dto.ts b/back/src/modules/share/dto/create-share.dto.ts deleted file mode 100644 index 2d51581..0000000 --- a/back/src/modules/share/dto/create-share.dto.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { IsNumber, IsNotEmpty } from 'class-validator'; -import { ApiProperty } from '@nestjs/swagger'; - -export class CreateShareDto { - @IsNumber() - @IsNotEmpty() - @ApiProperty({ type: Number, description: '유저 id' }) - readonly user_id: number; - - @IsNumber() - @IsNotEmpty() - @ApiProperty({ type: Number, description: '스노우볼 id' }) - readonly snowball_id: number; -} diff --git a/back/src/modules/share/dto/restore-share.dto.ts b/back/src/modules/share/dto/restore-share.dto.ts deleted file mode 100644 index 3402e34..0000000 --- a/back/src/modules/share/dto/restore-share.dto.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { IsString, IsNotEmpty } from 'class-validator'; -import { ApiProperty } from '@nestjs/swagger'; - -export class RestoreShareDto { - @IsString() - @IsNotEmpty() - @ApiProperty({ type: String, description: '암호화된 링크' }) - readonly encrypted_link: string; -} diff --git a/back/src/modules/share/share.controller.ts b/back/src/modules/share/share.controller.ts deleted file mode 100644 index 683f51d..0000000 --- a/back/src/modules/share/share.controller.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Controller, Post, Get, Body } from '@nestjs/common'; -import { ShareService } from './share.service'; -import { CreateShareDto } from './dto/create-share.dto'; -import { RestoreShareDto } from './dto/restore-share.dto'; -import { ApiOperation, ApiBody, ApiTags } from '@nestjs/swagger'; - -@ApiTags('Share API') -@Controller('share') -export class ShareController { - constructor(private readonly shareService: ShareService) {} - - @Post('create') - @ApiOperation({ - summary: '링크 생성 API', - description: '암호화된 링크를 생성합니다.' - }) - @ApiBody({ type: CreateShareDto }) - createShareLink(@Body() createShareDto: CreateShareDto) { - const encryptedLink = this.shareService.createShareLink(createShareDto); - return { encryptedLink }; - } - - @Get('restore') - @ApiOperation({ - summary: '링크 복원 API', - description: '암호화된 링크를 복원해 접속가능한 링크를 생성합니다.' - }) - @ApiBody({ type: RestoreShareDto }) - restoreShareLink(@Body() restoreShareDto: RestoreShareDto) { - const decryptedLink = this.shareService.restoreShareLink( - restoreShareDto.encrypted_link - ); - return { decryptedLink }; - } -} diff --git a/back/src/modules/share/share.module.ts b/back/src/modules/share/share.module.ts deleted file mode 100644 index 0b021de..0000000 --- a/back/src/modules/share/share.module.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Module } from '@nestjs/common'; -import { ShareController } from './share.controller'; -import { ShareService } from './share.service'; - -@Module({ - controllers: [ShareController], - providers: [ShareService] -}) -export class ShareModule {} diff --git a/back/src/modules/share/share.service.ts b/back/src/modules/share/share.service.ts deleted file mode 100644 index f5f8bbb..0000000 --- a/back/src/modules/share/share.service.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import * as crypto from 'crypto'; -import { CreateShareDto } from './dto/create-share.dto'; - -@Injectable() -export class ShareService { - private readonly secretKey: string = 'secret_key'; // 암호화 키 - createShareLink(createShareDto: CreateShareDto): string { - const dataToEncrypt = `${createShareDto.user_id}-${createShareDto.snowball_id}`; - const cipher = crypto.createCipher('aes-256-cbc', this.secretKey); - let encryptedLink = cipher.update(dataToEncrypt, 'utf-8', 'hex'); - encryptedLink += cipher.final('hex'); - return encryptedLink; - } - - restoreShareLink(encryptedLink: string): string { - const decipher = crypto.createDecipher('aes-256-cbc', this.secretKey); - let decryptedLink = decipher.update(encryptedLink, 'hex', 'utf-8'); - decryptedLink += decipher.final('utf-8'); - return decryptedLink; - } -} diff --git a/back/src/modules/snowball/dto/create-snowball.dto.ts b/back/src/modules/snowball/dto/create-snowball.dto.ts new file mode 100644 index 0000000..a8b6c45 --- /dev/null +++ b/back/src/modules/snowball/dto/create-snowball.dto.ts @@ -0,0 +1,45 @@ +import { + IsString, + IsNumber, + IsNotEmpty, + IsBoolean, + ValidateNested +} from '@nestjs/class-validator'; +import { ApiProperty } from '@nestjs/swagger'; +import { DecorationSnowballDto } from './decoration-snowball.dto'; + +export class CreateSnowballDto { + @IsNotEmpty() + @ValidateNested({ each: true }) + @ApiProperty({ + type: [DecorationSnowballDto], + description: '데코오브젝트들이 들어있는 리스트' + }) + readonly deco_list: DecorationSnowballDto[]; + + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '유저의 id' }) + readonly user_id: number; + + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '스노우볼 제목' }) + readonly title: string; + + @IsBoolean() + @IsNotEmpty() + @ApiProperty({ + type: Boolean, + description: '스노우볼 속 메시지들 비공개 여부를 가리키는 불리언' + }) + readonly message_private: boolean; + + @IsBoolean() + @IsNotEmpty() + @ApiProperty({ + type: Boolean, + description: '스노우볼 속 메시지 갯수의 비공개 여부를 가리키는 불리언' + }) + readonly message_count_private: boolean; +} diff --git a/back/src/modules/snowball/dto/decoration-snowball.dto.ts b/back/src/modules/snowball/dto/decoration-snowball.dto.ts new file mode 100644 index 0000000..64f312d --- /dev/null +++ b/back/src/modules/snowball/dto/decoration-snowball.dto.ts @@ -0,0 +1,14 @@ +import { IsNumber, IsNotEmpty } from '@nestjs/class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class DecorationSnowballDto { + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '데코레이션 id' }) + readonly deco_id: number; + + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '위치값' }) + readonly location: number; +} diff --git a/back/src/modules/snowball/dto/update-snowball.dto.ts b/back/src/modules/snowball/dto/update-snowball.dto.ts new file mode 100644 index 0000000..7831f09 --- /dev/null +++ b/back/src/modules/snowball/dto/update-snowball.dto.ts @@ -0,0 +1,35 @@ +import { + IsString, + IsNumber, + IsNotEmpty, + IsBoolean +} from '@nestjs/class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class UpdateSnowballDto { + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '유저의 id' }) + readonly user_id: number; + + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '스노우볼 제목' }) + readonly title: string; + + @IsBoolean() + @IsNotEmpty() + @ApiProperty({ + type: Boolean, + description: '스노우볼 속 메시지들 비공개 여부를 가리키는 불리언' + }) + readonly message_private: boolean; + + @IsBoolean() + @IsNotEmpty() + @ApiProperty({ + type: Boolean, + description: '스노우볼 속 메시지 갯수의 비공개 여부를 가리키는 불리언' + }) + readonly message_count_private: boolean; +} diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts new file mode 100644 index 0000000..1ecd3d7 --- /dev/null +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -0,0 +1,22 @@ +import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; + +@Entity({ name: 'snowball' }) +export class SnowballEntity { + @PrimaryGeneratedColumn() + id: number; + + @Column() + snowball_id: string; + + @Column() + user_id: number; + + @Column() + title: string; + + @Column({ nullable: true }) + private: string | null; + + @Column() + created_at: string; +} diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index dd40223..07d25ea 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -1,4 +1,31 @@ -import { Controller } from '@nestjs/common'; +import { Controller, Post, Put, Body } from '@nestjs/common'; +import { SnowballService } from './snowball.service'; +import { ApiBody, ApiTags, ApiOperation } from '@nestjs/swagger'; +import { CreateSnowballDto } from './dto/create-snowball.dto'; +import { UpdateSnowballDto } from './dto/update-snowball.dto'; +@ApiTags('Snowball API') @Controller('snowball') -export class SnowballController {} +export class SnowballController { + constructor(private readonly snowballService: SnowballService) {} + + @Post() + @ApiOperation({ + summary: '스노우볼 생성 API', + description: '스노우볼을 생성합니다.' + }) + @ApiBody({ type: CreateSnowballDto }) + createSnowball(@Body() createSnowballDto: CreateSnowballDto) { + return this.snowballService.createSnowball(createSnowballDto); + } + + @Put() + @ApiOperation({ + summary: '스노우볼 설정 업데이트 API', + description: '스노우볼에의 정보를 업데이트 해줍니다.' + }) + @ApiBody({ type: UpdateSnowballDto }) + updateSnowball(@Body() updateSnowballDto: UpdateSnowballDto) { + this.snowballService.updateSnowball(updateSnowballDto); + } +} diff --git a/back/src/modules/snowball/snowball.module.ts b/back/src/modules/snowball/snowball.module.ts index 197fdad..7e72f70 100644 --- a/back/src/modules/snowball/snowball.module.ts +++ b/back/src/modules/snowball/snowball.module.ts @@ -1,8 +1,12 @@ import { Module } from '@nestjs/common'; import { SnowballController } from './snowball.controller'; import { SnowballService } from './snowball.service'; +import { MessageModule } from '../message/message.module'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { SnowballEntity } from './entity/snowball.entity'; @Module({ + imports: [TypeOrmModule.forFeature([SnowballEntity]), MessageModule], controllers: [SnowballController], providers: [SnowballService] }) diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index e9ef044..a45fcaa 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -1,4 +1,23 @@ import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { SnowballEntity } from './entity/snowball.entity'; +import { CreateSnowballDto } from './dto/create-snowball.dto'; +import { UpdateSnowballDto } from './dto/update-snowball.dto'; @Injectable() -export class SnowballService {} +export class SnowballService { + constructor( + @InjectRepository(SnowballEntity) + private readonly snowballRepository: Repository + ) {} + async createSnowball( + createSnowballDto: CreateSnowballDto + ): Promise { + const snowball = this.snowballRepository.create(createSnowballDto); + return await this.snowballRepository.save(snowball); + } + async updateSnowball(updateSnowballDto: UpdateSnowballDto): Promise { + await this.snowballRepository.delete(updateSnowballDto.user_id); + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..685d6f2 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "ssock_hw", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} From bd71596aac7644f80771719c4b5be5424cca081a Mon Sep 17 00:00:00 2001 From: 5nxtnxtnxt <62386148+5nxtnxtnxt@users.noreply.github.com> Date: Thu, 16 Nov 2023 18:30:08 +0900 Subject: [PATCH 022/185] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6967100..dfbb06f 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ - + From 8a3a2140110830804db7f38feaca67bbd7454896 Mon Sep 17 00:00:00 2001 From: 5nxtnxtnxt <62386148+5nxtnxtnxt@users.noreply.github.com> Date: Thu, 16 Nov 2023 18:33:38 +0900 Subject: [PATCH 023/185] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dfbb06f..bdaa8fd 100644 --- a/README.md +++ b/README.md @@ -38,9 +38,9 @@ - + - + From c713c1f2da8cbd8b9d56b4474531294a32eaa280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Fri, 17 Nov 2023 04:20:20 +0900 Subject: [PATCH 024/185] =?UTF-8?q?feat:=20typeorm=20=EC=97=B0=EB=8F=99=20?= =?UTF-8?q?=EC=84=B1=EA=B3=B5=20!!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/package-lock.json | 13 +++++ back/package.json | 1 + .../modules/message/dto/create-message.dto.ts | 2 +- .../modules/message/entity/message.entity.ts | 15 ++++-- back/src/modules/message/message.service.ts | 2 +- .../entity/snowball-decoration.entity.ts | 27 ++++++++++ .../snowball/entity/snowball.entity.ts | 52 +++++++++++++++---- .../modules/snowball/entity/user.entity.ts | 29 +++++++++++ .../modules/snowball/snowball.controller.ts | 4 +- 9 files changed, 128 insertions(+), 17 deletions(-) create mode 100644 back/src/modules/snowball/entity/snowball-decoration.entity.ts create mode 100644 back/src/modules/snowball/entity/user.entity.ts diff --git a/back/package-lock.json b/back/package-lock.json index 9dfb1f0..ec6e8f2 100644 --- a/back/package-lock.json +++ b/back/package-lock.json @@ -37,6 +37,7 @@ "@types/jest": "^29.5.2", "@types/node": "^20.3.1", "@types/supertest": "^2.0.12", + "@types/uuid": "^9.0.7", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", "eslint": "^8.42.0", @@ -2374,6 +2375,12 @@ "@types/superagent": "*" } }, + "node_modules/@types/uuid": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", + "integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==", + "dev": true + }, "node_modules/@types/validator": { "version": "13.11.6", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.6.tgz", @@ -12460,6 +12467,12 @@ "@types/superagent": "*" } }, + "@types/uuid": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", + "integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==", + "dev": true + }, "@types/validator": { "version": "13.11.6", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.6.tgz", diff --git a/back/package.json b/back/package.json index 54d00cf..96fb911 100644 --- a/back/package.json +++ b/back/package.json @@ -48,6 +48,7 @@ "@types/jest": "^29.5.2", "@types/node": "^20.3.1", "@types/supertest": "^2.0.12", + "@types/uuid": "^9.0.7", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", "eslint": "^8.42.0", diff --git a/back/src/modules/message/dto/create-message.dto.ts b/back/src/modules/message/dto/create-message.dto.ts index 8ca2735..6860608 100644 --- a/back/src/modules/message/dto/create-message.dto.ts +++ b/back/src/modules/message/dto/create-message.dto.ts @@ -20,5 +20,5 @@ export class CreateMessageDto { @IsNumber() @IsNotEmpty() @ApiProperty({ type: Number, description: '데코오브젝트 id' }) - readonly deco_id: number; + readonly decoration_id: number; } diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index bd5c2bc..1d6ff21 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -2,8 +2,11 @@ import { Entity, Column, PrimaryGeneratedColumn, - CreateDateColumn + CreateDateColumn, + ManyToOne, + JoinColumn } from 'typeorm'; +import { SnowballEntity } from 'src/modules/snowball/entity/snowball.entity'; @Entity({ name: 'message' }) export class MessageEntity { @@ -14,7 +17,7 @@ export class MessageEntity { snowball_id: string; @Column() - deco_id: number; + decoration_id: number; @Column() content: string; @@ -22,9 +25,13 @@ export class MessageEntity { @Column() sender: string; - @Column({ nullable: true, default: null }) - opened: string | null; + @CreateDateColumn({ nullable: true, default: null }) + opened: Date | null; @CreateDateColumn() created_at: Date; + + @ManyToOne(() => SnowballEntity, message => message.message_snowballs) + @JoinColumn({ name: 'snowball_id' }) + message_snowballs: SnowballEntity; } diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index dc0709e..35c6138 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -16,7 +16,7 @@ export class MessageService { ): Promise { const messageEntity = this.messageRepository.create({ snowball_id: createMessageDto.snowball_id, - deco_id: createMessageDto.deco_id, + decoration_id: createMessageDto.decoration_id, content: createMessageDto.content, sender: createMessageDto.sender // opened와 created_at은 자동으로 설정됩니다. diff --git a/back/src/modules/snowball/entity/snowball-decoration.entity.ts b/back/src/modules/snowball/entity/snowball-decoration.entity.ts new file mode 100644 index 0000000..3d0ae21 --- /dev/null +++ b/back/src/modules/snowball/entity/snowball-decoration.entity.ts @@ -0,0 +1,27 @@ +import { + Entity, + Column, + PrimaryGeneratedColumn, + ManyToOne, + JoinColumn +} from 'typeorm'; +import { SnowballEntity } from './snowball.entity'; + +@Entity({ name: 'snowball_decoration' }) +export class SnowballDecorationEntity { + @PrimaryGeneratedColumn() + id: number; + + @Column() + snowball_id: number; + + @Column() + decoration_id: number; + + @Column() + location: number; + + @ManyToOne(() => SnowballEntity, deco => deco.deco_snowballs) + @JoinColumn({ name: 'snowball_id' }) + deco_snowballs: SnowballEntity; +} diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index 1ecd3d7..f72e71a 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -1,22 +1,56 @@ -import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; +import { IsUUID } from '@nestjs/class-validator'; +import { v4 as uuidv4 } from 'uuid'; +import { + Entity, + Column, + PrimaryGeneratedColumn, + CreateDateColumn, + ManyToOne, + OneToMany, + JoinColumn +} from 'typeorm'; +import { UserEntity } from './user.entity'; +import { SnowballDecorationEntity } from './snowball-decoration.entity'; +import { MessageEntity } from '../../message/entity/message.entity'; @Entity({ name: 'snowball' }) export class SnowballEntity { @PrimaryGeneratedColumn() id: number; - @Column() - snowball_id: string; - @Column() user_id: number; - @Column() + @IsUUID('4') + @Column({ length: 36 }) + snowball_uuid: string; + + @Column({ length: 16 }) title: string; - @Column({ nullable: true }) - private: string | null; + @CreateDateColumn() + created_at: Date; - @Column() - created_at: string; + @CreateDateColumn({ nullable: true, default: null }) + message_private: Date | null; + + @CreateDateColumn({ nullable: true, default: null }) + message_count_private: Date | null; + + @ManyToOne(() => UserEntity, user => user.snowballs) + @JoinColumn({ name: 'user_id' }) + user: UserEntity; + + @OneToMany(() => MessageEntity, message => message.snowball_id) + message_snowballs: MessageEntity[]; + + @OneToMany( + () => SnowballDecorationEntity, + snowball_deco => snowball_deco.snowball_id + ) + deco_snowballs: SnowballDecorationEntity[]; + + beforeInsert() { + this.snowball_uuid = uuidv4(); + } } diff --git a/back/src/modules/snowball/entity/user.entity.ts b/back/src/modules/snowball/entity/user.entity.ts new file mode 100644 index 0000000..b397bd7 --- /dev/null +++ b/back/src/modules/snowball/entity/user.entity.ts @@ -0,0 +1,29 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + OneToMany, + CreateDateColumn +} from 'typeorm'; +import { SnowballEntity } from './snowball.entity'; + +@Entity({ name: 'user' }) +export class UserEntity { + @PrimaryGeneratedColumn() + id: number; + + @Column({ length: 45 }) + user_id: string; + + @Column({ length: 16 }) + username: string; + + @Column({ length: 16 }) + provider: string; + + @CreateDateColumn() + created_at: Date; + + @OneToMany(() => SnowballEntity, snowball => snowball.user_id) + snowballs: SnowballEntity[]; +} diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index 07d25ea..1242023 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -16,7 +16,7 @@ export class SnowballController { }) @ApiBody({ type: CreateSnowballDto }) createSnowball(@Body() createSnowballDto: CreateSnowballDto) { - return this.snowballService.createSnowball(createSnowballDto); + return createSnowballDto; } @Put() @@ -26,6 +26,6 @@ export class SnowballController { }) @ApiBody({ type: UpdateSnowballDto }) updateSnowball(@Body() updateSnowballDto: UpdateSnowballDto) { - this.snowballService.updateSnowball(updateSnowballDto); + updateSnowballDto; } } From 1857c29535a35170d7d2c657a17f947b60b3dcce Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Fri, 17 Nov 2023 22:00:57 +0900 Subject: [PATCH 025/185] =?UTF-8?q?feat:=20erd=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/package-lock.json | 13 +++---------- back/package.json | 1 + back/src/modules/auth/auth.controller.ts | 12 ++++++------ back/src/modules/message/dto/create-message.dto.ts | 7 ++++++- back/src/modules/message/entity/message.entity.ts | 9 ++++++--- .../modules/snowball/dto/decoration-snowball.dto.ts | 9 +++++++-- .../snowball/entity/snowball-decoration.entity.ts | 5 ++++- back/src/modules/snowball/entity/snowball.entity.ts | 2 +- back/src/modules/snowball/entity/user.entity.ts | 2 +- 9 files changed, 35 insertions(+), 25 deletions(-) diff --git a/back/package-lock.json b/back/package-lock.json index ec6e8f2..b5f3b04 100644 --- a/back/package-lock.json +++ b/back/package-lock.json @@ -17,6 +17,7 @@ "@nestjs/platform-express": "^10.0.0", "@nestjs/swagger": "^7.1.16", "@nestjs/typeorm": "^10.0.0", + "class-validator": "^0.14.0", "dotenv": "^16.3.1", "mysql2": "^3.6.3", "passport": "^0.6.0", @@ -2384,9 +2385,7 @@ "node_modules/@types/validator": { "version": "13.11.6", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.6.tgz", - "integrity": "sha512-HUgHujPhKuNzgNXBRZKYexwoG+gHKU+tnfPqjWXFghZAnn73JElicMkuSKJyLGr9JgyA8IgK7fj88IyA9rwYeQ==", - "optional": true, - "peer": true + "integrity": "sha512-HUgHujPhKuNzgNXBRZKYexwoG+gHKU+tnfPqjWXFghZAnn73JElicMkuSKJyLGr9JgyA8IgK7fj88IyA9rwYeQ==" }, "node_modules/@types/yargs": { "version": "17.0.29", @@ -3675,8 +3674,6 @@ "version": "0.14.0", "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz", "integrity": "sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==", - "optional": true, - "peer": true, "dependencies": { "@types/validator": "^13.7.10", "libphonenumber-js": "^1.10.14", @@ -12476,9 +12473,7 @@ "@types/validator": { "version": "13.11.6", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.6.tgz", - "integrity": "sha512-HUgHujPhKuNzgNXBRZKYexwoG+gHKU+tnfPqjWXFghZAnn73JElicMkuSKJyLGr9JgyA8IgK7fj88IyA9rwYeQ==", - "optional": true, - "peer": true + "integrity": "sha512-HUgHujPhKuNzgNXBRZKYexwoG+gHKU+tnfPqjWXFghZAnn73JElicMkuSKJyLGr9JgyA8IgK7fj88IyA9rwYeQ==" }, "@types/yargs": { "version": "17.0.29", @@ -13417,8 +13412,6 @@ "version": "0.14.0", "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz", "integrity": "sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==", - "optional": true, - "peer": true, "requires": { "@types/validator": "^13.7.10", "libphonenumber-js": "^1.10.14", diff --git a/back/package.json b/back/package.json index 96fb911..8c63dd9 100644 --- a/back/package.json +++ b/back/package.json @@ -28,6 +28,7 @@ "@nestjs/platform-express": "^10.0.0", "@nestjs/swagger": "^7.1.16", "@nestjs/typeorm": "^10.0.0", + "class-validator": "^0.14.0", "dotenv": "^16.3.1", "mysql2": "^3.6.3", "passport": "^0.6.0", diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index bc1c0d4..a0a9bf1 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -17,11 +17,11 @@ export class AuthController { }) @ApiResponse({ status: 200, - description: `'http://localhost:3000/'으로 리다이렉트` + description: `'https://mysnowball.kr'로 리다이렉트` }) @ApiResponse({ status: 400, - description: `'http://localhost:3000/failure'으로 리다이렉트` + description: `'https://mysnowball.kr/failure'으로 리다이렉트` }) @UseGuards(AuthGuard('google')) async googleLogin(): Promise {} @@ -43,11 +43,11 @@ export class AuthController { }) @ApiResponse({ status: 200, - description: `'http://localhost:3000/'으로 리다이렉트` + description: `'https://mysnowball.kr'으로 리다이렉트` }) @ApiResponse({ status: 400, - description: `'http://localhost:3000/failure'으로 리다이렉트` + description: `'https://mysnowball.kr/failure'으로 리다이렉트` }) @UseGuards(AuthGuard('naver')) async naverLogin(): Promise {} @@ -69,11 +69,11 @@ export class AuthController { }) @ApiResponse({ status: 200, - description: `'http://localhost:3000/'으로 리다이렉트` + description: `'https://mysnowball.kr'으로 리다이렉트` }) @ApiResponse({ status: 400, - description: `'http://localhost:3000/failure'으로 리다이렉트` + description: `'https://mysnowball.kr/failure'으로 리다이렉트` }) @UseGuards(AuthGuard('kakao')) async kakaoLogin(): Promise {} diff --git a/back/src/modules/message/dto/create-message.dto.ts b/back/src/modules/message/dto/create-message.dto.ts index 6860608..45d1270 100644 --- a/back/src/modules/message/dto/create-message.dto.ts +++ b/back/src/modules/message/dto/create-message.dto.ts @@ -19,6 +19,11 @@ export class CreateMessageDto { @IsNumber() @IsNotEmpty() - @ApiProperty({ type: Number, description: '데코오브젝트 id' }) + @ApiProperty({ type: Number, description: '장식 종류' }) readonly decoration_id: number; + + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '장식 색상', example: '#FFFFFF' }) + readonly decoration_color: string; } diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 1d6ff21..389e7a4 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -8,7 +8,7 @@ import { } from 'typeorm'; import { SnowballEntity } from 'src/modules/snowball/entity/snowball.entity'; -@Entity({ name: 'message' }) +@Entity({ synchronize: true ,name: 'message' }) export class MessageEntity { @PrimaryGeneratedColumn() id: number; @@ -19,10 +19,13 @@ export class MessageEntity { @Column() decoration_id: number; - @Column() + @Column({ length: 7}) + decoration_color: string; + + @Column({ type: 'text' }) content: string; - @Column() + @Column({ length: 16}) sender: string; @CreateDateColumn({ nullable: true, default: null }) diff --git a/back/src/modules/snowball/dto/decoration-snowball.dto.ts b/back/src/modules/snowball/dto/decoration-snowball.dto.ts index 64f312d..d53f1a9 100644 --- a/back/src/modules/snowball/dto/decoration-snowball.dto.ts +++ b/back/src/modules/snowball/dto/decoration-snowball.dto.ts @@ -1,12 +1,17 @@ -import { IsNumber, IsNotEmpty } from '@nestjs/class-validator'; +import { IsNumber, IsNotEmpty, IsString } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class DecorationSnowballDto { @IsNumber() @IsNotEmpty() - @ApiProperty({ type: Number, description: '데코레이션 id' }) + @ApiProperty({ type: Number, description: '장식 종류' }) readonly deco_id: number; + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '장식 색상', example: '#FFFFFF' }) + readonly decoration_color: string; + @IsNumber() @IsNotEmpty() @ApiProperty({ type: Number, description: '위치값' }) diff --git a/back/src/modules/snowball/entity/snowball-decoration.entity.ts b/back/src/modules/snowball/entity/snowball-decoration.entity.ts index 3d0ae21..c9d6429 100644 --- a/back/src/modules/snowball/entity/snowball-decoration.entity.ts +++ b/back/src/modules/snowball/entity/snowball-decoration.entity.ts @@ -7,7 +7,7 @@ import { } from 'typeorm'; import { SnowballEntity } from './snowball.entity'; -@Entity({ name: 'snowball_decoration' }) +@Entity({ synchronize: true ,name: 'snowball_decoration' }) export class SnowballDecorationEntity { @PrimaryGeneratedColumn() id: number; @@ -18,6 +18,9 @@ export class SnowballDecorationEntity { @Column() decoration_id: number; + @Column({ length: 7}) + decoration_color: string; + @Column() location: number; diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index f72e71a..a207142 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -13,7 +13,7 @@ import { UserEntity } from './user.entity'; import { SnowballDecorationEntity } from './snowball-decoration.entity'; import { MessageEntity } from '../../message/entity/message.entity'; -@Entity({ name: 'snowball' }) +@Entity({ synchronize: true ,name: 'snowball' }) export class SnowballEntity { @PrimaryGeneratedColumn() id: number; diff --git a/back/src/modules/snowball/entity/user.entity.ts b/back/src/modules/snowball/entity/user.entity.ts index b397bd7..dbedafe 100644 --- a/back/src/modules/snowball/entity/user.entity.ts +++ b/back/src/modules/snowball/entity/user.entity.ts @@ -7,7 +7,7 @@ import { } from 'typeorm'; import { SnowballEntity } from './snowball.entity'; -@Entity({ name: 'user' }) +@Entity({synchronize: true , name: 'user' }) export class UserEntity { @PrimaryGeneratedColumn() id: number; From 4c55e20feefd36d11f0e926eb1287862a4027160 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Fri, 17 Nov 2023 22:16:15 +0900 Subject: [PATCH 026/185] =?UTF-8?q?feat:=20erm=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 685d6f2..96c6430 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "ssock_hw", + "name": "ssock", "lockfileVersion": 3, "requires": true, "packages": {} From d20a2774b7c7bf3e91f12025f60bbe26b6dce8e3 Mon Sep 17 00:00:00 2001 From: peageon Date: Sun, 19 Nov 2023 15:12:53 +0900 Subject: [PATCH 027/185] =?UTF-8?q?feat:=20response=20dto=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 0 -> 6148 bytes .../snowball/dto/decoration-snowball.dto.ts | 14 -------- ...ball.dto.ts => req-create-snowball.dto.ts} | 0 .../dto/req-decoration-snowball.dto.ts | 21 ++++++++++++ ...ball.dto.ts => req-update-snowball.dto.ts} | 0 .../snowball/dto/res-create-snowball.dto.ts | 32 ++++++++++++++++++ .../dto/res-decoration-snowball.dto.ts | 19 +++++++++++ .../snowball/dto/res-update-snowball.dto.ts | 30 ++++++++++++++++ .../modules/snowball/snowball.controller.ts | 21 ++++++++++-- back/src/modules/snowball/snowball.service.ts | 4 +-- 10 files changed, 122 insertions(+), 19 deletions(-) create mode 100644 .DS_Store delete mode 100644 back/src/modules/snowball/dto/decoration-snowball.dto.ts rename back/src/modules/snowball/dto/{create-snowball.dto.ts => req-create-snowball.dto.ts} (100%) create mode 100644 back/src/modules/snowball/dto/req-decoration-snowball.dto.ts rename back/src/modules/snowball/dto/{update-snowball.dto.ts => req-update-snowball.dto.ts} (100%) create mode 100644 back/src/modules/snowball/dto/res-create-snowball.dto.ts create mode 100644 back/src/modules/snowball/dto/res-decoration-snowball.dto.ts create mode 100644 back/src/modules/snowball/dto/res-update-snowball.dto.ts diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..027a2aeb0fbb7fa0680e1c7f67b680db86bab69d GIT binary patch literal 6148 zcmeHK%}T>S5Z-O0CKMqDg&r5Y7Ho|O;w8lT0!H+pQWH}&G-gYa+CwSitS{t~_&m<+ zZp31}ir5+0{pNQ!`$6`HF~);w(qqhJjM>l-IVvjz-77;4lZ?o5jCfXz<4ne2znR!y z2mE%6#Vlg?Z1nZ}<8hW2Ww-mz8%=9tbIZ2vmVFyO%2`-O<+KQ*$u(LRQf6_jNAYDk zoDJNaQ<;}hnhz(cAWepla&wjDiJS#;nkR*-4RyeF9B1IR=X1~VI^wX`TXe+y_@E2A zceGeI_U_*P$@yTEJ>~L66Uu>aCEEsTcm?HiJ Date: Sun, 19 Nov 2023 20:26:23 +0900 Subject: [PATCH 028/185] =?UTF-8?q?fix:=20response=20dto=20=EC=9E=98?= =?UTF-8?q?=EB=AA=BB=20=EC=9E=91=EC=84=B1=ED=95=9C=20=EB=B6=80=EB=B6=84=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../snowball/dto/decoration-snowball.ts | 19 ++++++++++++++ .../snowball/dto/req-create-snowball.dto.ts | 2 +- .../dto/req-decoration-snowball.dto.ts | 21 ---------------- .../snowball/dto/res-create-snowball.dto.ts | 25 ++++++++++--------- .../dto/res-decoration-snowball.dto.ts | 19 -------------- .../snowball/dto/res-update-snowball.dto.ts | 2 +- 6 files changed, 34 insertions(+), 54 deletions(-) create mode 100644 back/src/modules/snowball/dto/decoration-snowball.ts delete mode 100644 back/src/modules/snowball/dto/req-decoration-snowball.dto.ts delete mode 100644 back/src/modules/snowball/dto/res-decoration-snowball.dto.ts diff --git a/back/src/modules/snowball/dto/decoration-snowball.ts b/back/src/modules/snowball/dto/decoration-snowball.ts new file mode 100644 index 0000000..d53f1a9 --- /dev/null +++ b/back/src/modules/snowball/dto/decoration-snowball.ts @@ -0,0 +1,19 @@ +import { IsNumber, IsNotEmpty, IsString } from '@nestjs/class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class DecorationSnowballDto { + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '장식 종류' }) + readonly deco_id: number; + + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '장식 색상', example: '#FFFFFF' }) + readonly decoration_color: string; + + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '위치값' }) + readonly location: number; +} diff --git a/back/src/modules/snowball/dto/req-create-snowball.dto.ts b/back/src/modules/snowball/dto/req-create-snowball.dto.ts index a8b6c45..7d984a0 100644 --- a/back/src/modules/snowball/dto/req-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/req-create-snowball.dto.ts @@ -6,7 +6,7 @@ import { ValidateNested } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -import { DecorationSnowballDto } from './decoration-snowball.dto'; +import { DecorationSnowballDto } from './decoration-snowball'; export class CreateSnowballDto { @IsNotEmpty() diff --git a/back/src/modules/snowball/dto/req-decoration-snowball.dto.ts b/back/src/modules/snowball/dto/req-decoration-snowball.dto.ts deleted file mode 100644 index 3c202a2..0000000 --- a/back/src/modules/snowball/dto/req-decoration-snowball.dto.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { IsNotEmpty, ValidateNested, IsUUID } from '@nestjs/class-validator'; -import { ApiProperty } from '@nestjs/swagger'; - -export class DecorationSnowballDto { - @IsUUID() - @IsNotEmpty() - @ApiProperty({ - type: String, - description: '스노우볼 uuid', - format: 'uuid' - }) - readonly snowball_id: string; - - @IsNotEmpty() - @ValidateNested({ each: true }) - @ApiProperty({ - type: [DecorationSnowballDto], - description: '데코오브젝트들이 들어있는 리스트' - }) - readonly deco_list: DecorationSnowballDto[]; -} diff --git a/back/src/modules/snowball/dto/res-create-snowball.dto.ts b/back/src/modules/snowball/dto/res-create-snowball.dto.ts index d70b09e..3016107 100644 --- a/back/src/modules/snowball/dto/res-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/res-create-snowball.dto.ts @@ -1,11 +1,9 @@ +import { IsBoolean, ValidateNested } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -import { IsNumber, IsString, IsDate, IsUUID } from 'class-validator'; +import { IsString, IsDate, IsUUID } from 'class-validator'; +import { DecorationSnowballDto } from './decoration-snowball'; export class ResCreateSnowballDto { - @ApiProperty({ description: '스노우볼을 만든 유저의 id' }) - @IsUUID() - user_id: string; - @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) @IsUUID() snowball_uuid: string; @@ -14,17 +12,20 @@ export class ResCreateSnowballDto { @IsString() title: string; - @ApiProperty({ description: '스노우볼 안에 생성된 데코레이션들의 정보' }) - @IsString({ each: true }) - decoration_list: string[]; + @ValidateNested({ each: true }) + @ApiProperty({ + type: [DecorationSnowballDto], + description: '데코오브젝트들이 들어있는 리스트' + }) + readonly deco_list: DecorationSnowballDto[]; @ApiProperty({ description: '메시지들의 공개 여부 (True이면 비공개)' }) - @IsString() - message_private: string; + @IsBoolean() + message_private: boolean; @ApiProperty({ description: '받은 메시지 수 공개 여부 (True이면 비공개)' }) - @IsNumber() - message_count_private: number; + @IsBoolean() + message_count_private: boolean; @ApiProperty({ description: '스노우볼이 언제 생성되었는지' }) @IsDate() diff --git a/back/src/modules/snowball/dto/res-decoration-snowball.dto.ts b/back/src/modules/snowball/dto/res-decoration-snowball.dto.ts deleted file mode 100644 index a6ca579..0000000 --- a/back/src/modules/snowball/dto/res-decoration-snowball.dto.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ValidateNested, IsUUID } from '@nestjs/class-validator'; -import { ApiProperty } from '@nestjs/swagger'; - -export class DecorationSnowballDto { - @IsUUID() - @ApiProperty({ - type: String, - description: '업데이트된 스노우볼 uuid', - format: 'uuid' - }) - readonly snowball_id: string; - - @ValidateNested({ each: true }) - @ApiProperty({ - type: [DecorationSnowballDto], - description: '업데이트된 데코오브젝트들이 들어있는 리스트' - }) - readonly deco_list: DecorationSnowballDto[]; -} diff --git a/back/src/modules/snowball/dto/res-update-snowball.dto.ts b/back/src/modules/snowball/dto/res-update-snowball.dto.ts index f9cae0b..a2d6324 100644 --- a/back/src/modules/snowball/dto/res-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/res-update-snowball.dto.ts @@ -1,7 +1,7 @@ import { IsString, IsUUID, IsBoolean } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -export class UpdateSnowballDto { +export class ResUpdateSnowballDto { @IsUUID() @ApiProperty({ type: String, From 26de229fa28333bdc897524f272bc56a2ea17825 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Fri, 17 Nov 2023 22:00:57 +0900 Subject: [PATCH 029/185] =?UTF-8?q?feat:=20erd=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/package-lock.json | 13 +++---------- back/package.json | 1 + back/src/modules/auth/auth.controller.ts | 12 ++++++------ back/src/modules/message/dto/create-message.dto.ts | 7 ++++++- back/src/modules/message/entity/message.entity.ts | 9 ++++++--- .../snowball/entity/snowball-decoration.entity.ts | 5 ++++- back/src/modules/snowball/entity/snowball.entity.ts | 2 +- back/src/modules/snowball/entity/user.entity.ts | 2 +- 8 files changed, 28 insertions(+), 23 deletions(-) diff --git a/back/package-lock.json b/back/package-lock.json index ec6e8f2..b5f3b04 100644 --- a/back/package-lock.json +++ b/back/package-lock.json @@ -17,6 +17,7 @@ "@nestjs/platform-express": "^10.0.0", "@nestjs/swagger": "^7.1.16", "@nestjs/typeorm": "^10.0.0", + "class-validator": "^0.14.0", "dotenv": "^16.3.1", "mysql2": "^3.6.3", "passport": "^0.6.0", @@ -2384,9 +2385,7 @@ "node_modules/@types/validator": { "version": "13.11.6", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.6.tgz", - "integrity": "sha512-HUgHujPhKuNzgNXBRZKYexwoG+gHKU+tnfPqjWXFghZAnn73JElicMkuSKJyLGr9JgyA8IgK7fj88IyA9rwYeQ==", - "optional": true, - "peer": true + "integrity": "sha512-HUgHujPhKuNzgNXBRZKYexwoG+gHKU+tnfPqjWXFghZAnn73JElicMkuSKJyLGr9JgyA8IgK7fj88IyA9rwYeQ==" }, "node_modules/@types/yargs": { "version": "17.0.29", @@ -3675,8 +3674,6 @@ "version": "0.14.0", "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz", "integrity": "sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==", - "optional": true, - "peer": true, "dependencies": { "@types/validator": "^13.7.10", "libphonenumber-js": "^1.10.14", @@ -12476,9 +12473,7 @@ "@types/validator": { "version": "13.11.6", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.6.tgz", - "integrity": "sha512-HUgHujPhKuNzgNXBRZKYexwoG+gHKU+tnfPqjWXFghZAnn73JElicMkuSKJyLGr9JgyA8IgK7fj88IyA9rwYeQ==", - "optional": true, - "peer": true + "integrity": "sha512-HUgHujPhKuNzgNXBRZKYexwoG+gHKU+tnfPqjWXFghZAnn73JElicMkuSKJyLGr9JgyA8IgK7fj88IyA9rwYeQ==" }, "@types/yargs": { "version": "17.0.29", @@ -13417,8 +13412,6 @@ "version": "0.14.0", "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz", "integrity": "sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==", - "optional": true, - "peer": true, "requires": { "@types/validator": "^13.7.10", "libphonenumber-js": "^1.10.14", diff --git a/back/package.json b/back/package.json index 96fb911..8c63dd9 100644 --- a/back/package.json +++ b/back/package.json @@ -28,6 +28,7 @@ "@nestjs/platform-express": "^10.0.0", "@nestjs/swagger": "^7.1.16", "@nestjs/typeorm": "^10.0.0", + "class-validator": "^0.14.0", "dotenv": "^16.3.1", "mysql2": "^3.6.3", "passport": "^0.6.0", diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index bc1c0d4..a0a9bf1 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -17,11 +17,11 @@ export class AuthController { }) @ApiResponse({ status: 200, - description: `'http://localhost:3000/'으로 리다이렉트` + description: `'https://mysnowball.kr'로 리다이렉트` }) @ApiResponse({ status: 400, - description: `'http://localhost:3000/failure'으로 리다이렉트` + description: `'https://mysnowball.kr/failure'으로 리다이렉트` }) @UseGuards(AuthGuard('google')) async googleLogin(): Promise {} @@ -43,11 +43,11 @@ export class AuthController { }) @ApiResponse({ status: 200, - description: `'http://localhost:3000/'으로 리다이렉트` + description: `'https://mysnowball.kr'으로 리다이렉트` }) @ApiResponse({ status: 400, - description: `'http://localhost:3000/failure'으로 리다이렉트` + description: `'https://mysnowball.kr/failure'으로 리다이렉트` }) @UseGuards(AuthGuard('naver')) async naverLogin(): Promise {} @@ -69,11 +69,11 @@ export class AuthController { }) @ApiResponse({ status: 200, - description: `'http://localhost:3000/'으로 리다이렉트` + description: `'https://mysnowball.kr'으로 리다이렉트` }) @ApiResponse({ status: 400, - description: `'http://localhost:3000/failure'으로 리다이렉트` + description: `'https://mysnowball.kr/failure'으로 리다이렉트` }) @UseGuards(AuthGuard('kakao')) async kakaoLogin(): Promise {} diff --git a/back/src/modules/message/dto/create-message.dto.ts b/back/src/modules/message/dto/create-message.dto.ts index 6860608..45d1270 100644 --- a/back/src/modules/message/dto/create-message.dto.ts +++ b/back/src/modules/message/dto/create-message.dto.ts @@ -19,6 +19,11 @@ export class CreateMessageDto { @IsNumber() @IsNotEmpty() - @ApiProperty({ type: Number, description: '데코오브젝트 id' }) + @ApiProperty({ type: Number, description: '장식 종류' }) readonly decoration_id: number; + + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '장식 색상', example: '#FFFFFF' }) + readonly decoration_color: string; } diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 1d6ff21..389e7a4 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -8,7 +8,7 @@ import { } from 'typeorm'; import { SnowballEntity } from 'src/modules/snowball/entity/snowball.entity'; -@Entity({ name: 'message' }) +@Entity({ synchronize: true ,name: 'message' }) export class MessageEntity { @PrimaryGeneratedColumn() id: number; @@ -19,10 +19,13 @@ export class MessageEntity { @Column() decoration_id: number; - @Column() + @Column({ length: 7}) + decoration_color: string; + + @Column({ type: 'text' }) content: string; - @Column() + @Column({ length: 16}) sender: string; @CreateDateColumn({ nullable: true, default: null }) diff --git a/back/src/modules/snowball/entity/snowball-decoration.entity.ts b/back/src/modules/snowball/entity/snowball-decoration.entity.ts index 3d0ae21..c9d6429 100644 --- a/back/src/modules/snowball/entity/snowball-decoration.entity.ts +++ b/back/src/modules/snowball/entity/snowball-decoration.entity.ts @@ -7,7 +7,7 @@ import { } from 'typeorm'; import { SnowballEntity } from './snowball.entity'; -@Entity({ name: 'snowball_decoration' }) +@Entity({ synchronize: true ,name: 'snowball_decoration' }) export class SnowballDecorationEntity { @PrimaryGeneratedColumn() id: number; @@ -18,6 +18,9 @@ export class SnowballDecorationEntity { @Column() decoration_id: number; + @Column({ length: 7}) + decoration_color: string; + @Column() location: number; diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index f72e71a..a207142 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -13,7 +13,7 @@ import { UserEntity } from './user.entity'; import { SnowballDecorationEntity } from './snowball-decoration.entity'; import { MessageEntity } from '../../message/entity/message.entity'; -@Entity({ name: 'snowball' }) +@Entity({ synchronize: true ,name: 'snowball' }) export class SnowballEntity { @PrimaryGeneratedColumn() id: number; diff --git a/back/src/modules/snowball/entity/user.entity.ts b/back/src/modules/snowball/entity/user.entity.ts index b397bd7..dbedafe 100644 --- a/back/src/modules/snowball/entity/user.entity.ts +++ b/back/src/modules/snowball/entity/user.entity.ts @@ -7,7 +7,7 @@ import { } from 'typeorm'; import { SnowballEntity } from './snowball.entity'; -@Entity({ name: 'user' }) +@Entity({synchronize: true , name: 'user' }) export class UserEntity { @PrimaryGeneratedColumn() id: number; From 4d44b3a22ed7addd60d26bc76ebaae3a49d2cbc0 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Fri, 17 Nov 2023 22:16:15 +0900 Subject: [PATCH 030/185] =?UTF-8?q?feat:=20erm=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 685d6f2..96c6430 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "ssock_hw", + "name": "ssock", "lockfileVersion": 3, "requires": true, "packages": {} From a3539f58f38b51ab2ddcee14b19f15d017263fbe Mon Sep 17 00:00:00 2001 From: peageon Date: Sun, 19 Nov 2023 15:12:53 +0900 Subject: [PATCH 031/185] =?UTF-8?q?feat:=20response=20dto=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/req-decoration-snowball.dto.ts | 21 ++++++++++++++++ .../snowball/dto/res-create-snowball.dto.ts | 25 +++++++++++++++++++ .../dto/res-decoration-snowball.dto.ts | 19 ++++++++++++++ .../snowball/dto/res-update-snowball.dto.ts | 4 +++ 4 files changed, 69 insertions(+) create mode 100644 back/src/modules/snowball/dto/req-decoration-snowball.dto.ts create mode 100644 back/src/modules/snowball/dto/res-decoration-snowball.dto.ts diff --git a/back/src/modules/snowball/dto/req-decoration-snowball.dto.ts b/back/src/modules/snowball/dto/req-decoration-snowball.dto.ts new file mode 100644 index 0000000..3c202a2 --- /dev/null +++ b/back/src/modules/snowball/dto/req-decoration-snowball.dto.ts @@ -0,0 +1,21 @@ +import { IsNotEmpty, ValidateNested, IsUUID } from '@nestjs/class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class DecorationSnowballDto { + @IsUUID() + @IsNotEmpty() + @ApiProperty({ + type: String, + description: '스노우볼 uuid', + format: 'uuid' + }) + readonly snowball_id: string; + + @IsNotEmpty() + @ValidateNested({ each: true }) + @ApiProperty({ + type: [DecorationSnowballDto], + description: '데코오브젝트들이 들어있는 리스트' + }) + readonly deco_list: DecorationSnowballDto[]; +} diff --git a/back/src/modules/snowball/dto/res-create-snowball.dto.ts b/back/src/modules/snowball/dto/res-create-snowball.dto.ts index 3016107..849cd24 100644 --- a/back/src/modules/snowball/dto/res-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/res-create-snowball.dto.ts @@ -1,9 +1,20 @@ +<<<<<<< HEAD import { IsBoolean, ValidateNested } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; import { IsString, IsDate, IsUUID } from 'class-validator'; import { DecorationSnowballDto } from './decoration-snowball'; export class ResCreateSnowballDto { +======= +import { ApiProperty } from '@nestjs/swagger'; +import { IsNumber, IsString, IsDate, IsUUID } from 'class-validator'; + +export class ResCreateSnowballDto { + @ApiProperty({ description: '스노우볼을 만든 유저의 id' }) + @IsUUID() + user_id: string; + +>>>>>>> a3e84de (feat: response dto 생성) @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) @IsUUID() snowball_uuid: string; @@ -12,6 +23,7 @@ export class ResCreateSnowballDto { @IsString() title: string; +<<<<<<< HEAD @ValidateNested({ each: true }) @ApiProperty({ type: [DecorationSnowballDto], @@ -26,6 +38,19 @@ export class ResCreateSnowballDto { @ApiProperty({ description: '받은 메시지 수 공개 여부 (True이면 비공개)' }) @IsBoolean() message_count_private: boolean; +======= + @ApiProperty({ description: '스노우볼 안에 생성된 데코레이션들의 정보' }) + @IsString({ each: true }) + decoration_list: string[]; + + @ApiProperty({ description: '메시지들의 공개 여부 (True이면 비공개)' }) + @IsString() + message_private: string; + + @ApiProperty({ description: '받은 메시지 수 공개 여부 (True이면 비공개)' }) + @IsNumber() + message_count_private: number; +>>>>>>> a3e84de (feat: response dto 생성) @ApiProperty({ description: '스노우볼이 언제 생성되었는지' }) @IsDate() diff --git a/back/src/modules/snowball/dto/res-decoration-snowball.dto.ts b/back/src/modules/snowball/dto/res-decoration-snowball.dto.ts new file mode 100644 index 0000000..a6ca579 --- /dev/null +++ b/back/src/modules/snowball/dto/res-decoration-snowball.dto.ts @@ -0,0 +1,19 @@ +import { ValidateNested, IsUUID } from '@nestjs/class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class DecorationSnowballDto { + @IsUUID() + @ApiProperty({ + type: String, + description: '업데이트된 스노우볼 uuid', + format: 'uuid' + }) + readonly snowball_id: string; + + @ValidateNested({ each: true }) + @ApiProperty({ + type: [DecorationSnowballDto], + description: '업데이트된 데코오브젝트들이 들어있는 리스트' + }) + readonly deco_list: DecorationSnowballDto[]; +} diff --git a/back/src/modules/snowball/dto/res-update-snowball.dto.ts b/back/src/modules/snowball/dto/res-update-snowball.dto.ts index a2d6324..e717152 100644 --- a/back/src/modules/snowball/dto/res-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/res-update-snowball.dto.ts @@ -1,7 +1,11 @@ import { IsString, IsUUID, IsBoolean } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; +<<<<<<< HEAD export class ResUpdateSnowballDto { +======= +export class UpdateSnowballDto { +>>>>>>> a3e84de (feat: response dto 생성) @IsUUID() @ApiProperty({ type: String, From 724d171362748161df25b4763c9bdacdfb498f41 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Fri, 17 Nov 2023 22:00:57 +0900 Subject: [PATCH 032/185] =?UTF-8?q?feat:=20erd=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../snowball/dto/decoration-snowball.dto.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 back/src/modules/snowball/dto/decoration-snowball.dto.ts diff --git a/back/src/modules/snowball/dto/decoration-snowball.dto.ts b/back/src/modules/snowball/dto/decoration-snowball.dto.ts new file mode 100644 index 0000000..d53f1a9 --- /dev/null +++ b/back/src/modules/snowball/dto/decoration-snowball.dto.ts @@ -0,0 +1,19 @@ +import { IsNumber, IsNotEmpty, IsString } from '@nestjs/class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class DecorationSnowballDto { + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '장식 종류' }) + readonly deco_id: number; + + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '장식 색상', example: '#FFFFFF' }) + readonly decoration_color: string; + + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '위치값' }) + readonly location: number; +} From 449f93bd64fd829c9e076e64a2d3a2bf594c34e0 Mon Sep 17 00:00:00 2001 From: peageon Date: Sun, 19 Nov 2023 15:12:53 +0900 Subject: [PATCH 033/185] =?UTF-8?q?feat:=20response=20dto=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/snowball/dto/res-create-snowball.dto.ts | 12 ++++++++++++ .../modules/snowball/dto/res-update-snowball.dto.ts | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/back/src/modules/snowball/dto/res-create-snowball.dto.ts b/back/src/modules/snowball/dto/res-create-snowball.dto.ts index 849cd24..eccbf5b 100644 --- a/back/src/modules/snowball/dto/res-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/res-create-snowball.dto.ts @@ -1,4 +1,5 @@ <<<<<<< HEAD +<<<<<<< HEAD import { IsBoolean, ValidateNested } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; import { IsString, IsDate, IsUUID } from 'class-validator'; @@ -6,6 +7,8 @@ import { DecorationSnowballDto } from './decoration-snowball'; export class ResCreateSnowballDto { ======= +======= +>>>>>>> 651d544 (feat: response dto 생성) import { ApiProperty } from '@nestjs/swagger'; import { IsNumber, IsString, IsDate, IsUUID } from 'class-validator'; @@ -14,7 +17,10 @@ export class ResCreateSnowballDto { @IsUUID() user_id: string; +<<<<<<< HEAD >>>>>>> a3e84de (feat: response dto 생성) +======= +>>>>>>> 651d544 (feat: response dto 생성) @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) @IsUUID() snowball_uuid: string; @@ -23,6 +29,7 @@ export class ResCreateSnowballDto { @IsString() title: string; +<<<<<<< HEAD <<<<<<< HEAD @ValidateNested({ each: true }) @ApiProperty({ @@ -39,6 +46,8 @@ export class ResCreateSnowballDto { @IsBoolean() message_count_private: boolean; ======= +======= +>>>>>>> 651d544 (feat: response dto 생성) @ApiProperty({ description: '스노우볼 안에 생성된 데코레이션들의 정보' }) @IsString({ each: true }) decoration_list: string[]; @@ -50,7 +59,10 @@ export class ResCreateSnowballDto { @ApiProperty({ description: '받은 메시지 수 공개 여부 (True이면 비공개)' }) @IsNumber() message_count_private: number; +<<<<<<< HEAD >>>>>>> a3e84de (feat: response dto 생성) +======= +>>>>>>> 651d544 (feat: response dto 생성) @ApiProperty({ description: '스노우볼이 언제 생성되었는지' }) @IsDate() diff --git a/back/src/modules/snowball/dto/res-update-snowball.dto.ts b/back/src/modules/snowball/dto/res-update-snowball.dto.ts index e717152..ac9df25 100644 --- a/back/src/modules/snowball/dto/res-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/res-update-snowball.dto.ts @@ -1,11 +1,15 @@ import { IsString, IsUUID, IsBoolean } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; +<<<<<<< HEAD <<<<<<< HEAD export class ResUpdateSnowballDto { ======= export class UpdateSnowballDto { >>>>>>> a3e84de (feat: response dto 생성) +======= +export class UpdateSnowballDto { +>>>>>>> 651d544 (feat: response dto 생성) @IsUUID() @ApiProperty({ type: String, From 41bfda7a638aaca6948adef55b307e05cc1daa23 Mon Sep 17 00:00:00 2001 From: peageon Date: Sun, 19 Nov 2023 20:49:51 +0900 Subject: [PATCH 034/185] =?UTF-8?q?fix:=20=EA=B9=83=20=EA=B3=A0=EC=B9=98?= =?UTF-8?q?=EB=8A=94=20=EC=A4=91=EC=97=90=20=EB=B0=9C=EC=83=9D=ED=95=9C=20?= =?UTF-8?q?merge=20conflict=20markers=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../snowball/dto/decoration-snowball.ts | 19 ------- .../snowball/dto/res-create-snowball.dto.ts | 56 +------------------ .../snowball/dto/res-update-snowball.dto.ts | 8 --- 3 files changed, 1 insertion(+), 82 deletions(-) delete mode 100644 back/src/modules/snowball/dto/decoration-snowball.ts diff --git a/back/src/modules/snowball/dto/decoration-snowball.ts b/back/src/modules/snowball/dto/decoration-snowball.ts deleted file mode 100644 index d53f1a9..0000000 --- a/back/src/modules/snowball/dto/decoration-snowball.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { IsNumber, IsNotEmpty, IsString } from '@nestjs/class-validator'; -import { ApiProperty } from '@nestjs/swagger'; - -export class DecorationSnowballDto { - @IsNumber() - @IsNotEmpty() - @ApiProperty({ type: Number, description: '장식 종류' }) - readonly deco_id: number; - - @IsString() - @IsNotEmpty() - @ApiProperty({ type: String, description: '장식 색상', example: '#FFFFFF' }) - readonly decoration_color: string; - - @IsNumber() - @IsNotEmpty() - @ApiProperty({ type: Number, description: '위치값' }) - readonly location: number; -} diff --git a/back/src/modules/snowball/dto/res-create-snowball.dto.ts b/back/src/modules/snowball/dto/res-create-snowball.dto.ts index eccbf5b..658a632 100644 --- a/back/src/modules/snowball/dto/res-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/res-create-snowball.dto.ts @@ -1,26 +1,11 @@ -<<<<<<< HEAD -<<<<<<< HEAD -import { IsBoolean, ValidateNested } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -import { IsString, IsDate, IsUUID } from 'class-validator'; -import { DecorationSnowballDto } from './decoration-snowball'; - -export class ResCreateSnowballDto { -======= -======= ->>>>>>> 651d544 (feat: response dto 생성) -import { ApiProperty } from '@nestjs/swagger'; -import { IsNumber, IsString, IsDate, IsUUID } from 'class-validator'; +import { IsString, IsUUID } from 'class-validator'; export class ResCreateSnowballDto { @ApiProperty({ description: '스노우볼을 만든 유저의 id' }) @IsUUID() user_id: string; -<<<<<<< HEAD ->>>>>>> a3e84de (feat: response dto 생성) -======= ->>>>>>> 651d544 (feat: response dto 생성) @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) @IsUUID() snowball_uuid: string; @@ -28,43 +13,4 @@ export class ResCreateSnowballDto { @ApiProperty({ description: '생성된 스노우볼의 제목' }) @IsString() title: string; - -<<<<<<< HEAD -<<<<<<< HEAD - @ValidateNested({ each: true }) - @ApiProperty({ - type: [DecorationSnowballDto], - description: '데코오브젝트들이 들어있는 리스트' - }) - readonly deco_list: DecorationSnowballDto[]; - - @ApiProperty({ description: '메시지들의 공개 여부 (True이면 비공개)' }) - @IsBoolean() - message_private: boolean; - - @ApiProperty({ description: '받은 메시지 수 공개 여부 (True이면 비공개)' }) - @IsBoolean() - message_count_private: boolean; -======= -======= ->>>>>>> 651d544 (feat: response dto 생성) - @ApiProperty({ description: '스노우볼 안에 생성된 데코레이션들의 정보' }) - @IsString({ each: true }) - decoration_list: string[]; - - @ApiProperty({ description: '메시지들의 공개 여부 (True이면 비공개)' }) - @IsString() - message_private: string; - - @ApiProperty({ description: '받은 메시지 수 공개 여부 (True이면 비공개)' }) - @IsNumber() - message_count_private: number; -<<<<<<< HEAD ->>>>>>> a3e84de (feat: response dto 생성) -======= ->>>>>>> 651d544 (feat: response dto 생성) - - @ApiProperty({ description: '스노우볼이 언제 생성되었는지' }) - @IsDate() - createdAt: Date; } diff --git a/back/src/modules/snowball/dto/res-update-snowball.dto.ts b/back/src/modules/snowball/dto/res-update-snowball.dto.ts index ac9df25..a2d6324 100644 --- a/back/src/modules/snowball/dto/res-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/res-update-snowball.dto.ts @@ -1,15 +1,7 @@ import { IsString, IsUUID, IsBoolean } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -<<<<<<< HEAD -<<<<<<< HEAD export class ResUpdateSnowballDto { -======= -export class UpdateSnowballDto { ->>>>>>> a3e84de (feat: response dto 생성) -======= -export class UpdateSnowballDto { ->>>>>>> 651d544 (feat: response dto 생성) @IsUUID() @ApiProperty({ type: String, From 1feb5bf6e3f3e662ca59894ae6a1dc26f2047b56 Mon Sep 17 00:00:00 2001 From: peageon Date: Sun, 19 Nov 2023 20:53:12 +0900 Subject: [PATCH 035/185] =?UTF-8?q?fix:=20merge=20conflict=20=ED=95=A0?= =?UTF-8?q?=EB=95=8C=20=EC=9E=98=20=EC=95=88=EB=90=9C=20=EB=B6=80=EB=B6=84?= =?UTF-8?q?=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../snowball/dto/req-create-snowball.dto.ts | 2 +- .../dto/req-decoration-snowball.dto.ts | 21 ------------------- .../dto/res-decoration-snowball.dto.ts | 19 ----------------- .../entity/snowball-decoration.entity.ts | 4 ++-- .../snowball/entity/snowball.entity.ts | 2 +- .../modules/snowball/entity/user.entity.ts | 2 +- 6 files changed, 5 insertions(+), 45 deletions(-) delete mode 100644 back/src/modules/snowball/dto/req-decoration-snowball.dto.ts delete mode 100644 back/src/modules/snowball/dto/res-decoration-snowball.dto.ts diff --git a/back/src/modules/snowball/dto/req-create-snowball.dto.ts b/back/src/modules/snowball/dto/req-create-snowball.dto.ts index 7d984a0..a8b6c45 100644 --- a/back/src/modules/snowball/dto/req-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/req-create-snowball.dto.ts @@ -6,7 +6,7 @@ import { ValidateNested } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -import { DecorationSnowballDto } from './decoration-snowball'; +import { DecorationSnowballDto } from './decoration-snowball.dto'; export class CreateSnowballDto { @IsNotEmpty() diff --git a/back/src/modules/snowball/dto/req-decoration-snowball.dto.ts b/back/src/modules/snowball/dto/req-decoration-snowball.dto.ts deleted file mode 100644 index 3c202a2..0000000 --- a/back/src/modules/snowball/dto/req-decoration-snowball.dto.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { IsNotEmpty, ValidateNested, IsUUID } from '@nestjs/class-validator'; -import { ApiProperty } from '@nestjs/swagger'; - -export class DecorationSnowballDto { - @IsUUID() - @IsNotEmpty() - @ApiProperty({ - type: String, - description: '스노우볼 uuid', - format: 'uuid' - }) - readonly snowball_id: string; - - @IsNotEmpty() - @ValidateNested({ each: true }) - @ApiProperty({ - type: [DecorationSnowballDto], - description: '데코오브젝트들이 들어있는 리스트' - }) - readonly deco_list: DecorationSnowballDto[]; -} diff --git a/back/src/modules/snowball/dto/res-decoration-snowball.dto.ts b/back/src/modules/snowball/dto/res-decoration-snowball.dto.ts deleted file mode 100644 index a6ca579..0000000 --- a/back/src/modules/snowball/dto/res-decoration-snowball.dto.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ValidateNested, IsUUID } from '@nestjs/class-validator'; -import { ApiProperty } from '@nestjs/swagger'; - -export class DecorationSnowballDto { - @IsUUID() - @ApiProperty({ - type: String, - description: '업데이트된 스노우볼 uuid', - format: 'uuid' - }) - readonly snowball_id: string; - - @ValidateNested({ each: true }) - @ApiProperty({ - type: [DecorationSnowballDto], - description: '업데이트된 데코오브젝트들이 들어있는 리스트' - }) - readonly deco_list: DecorationSnowballDto[]; -} diff --git a/back/src/modules/snowball/entity/snowball-decoration.entity.ts b/back/src/modules/snowball/entity/snowball-decoration.entity.ts index c9d6429..4667890 100644 --- a/back/src/modules/snowball/entity/snowball-decoration.entity.ts +++ b/back/src/modules/snowball/entity/snowball-decoration.entity.ts @@ -7,7 +7,7 @@ import { } from 'typeorm'; import { SnowballEntity } from './snowball.entity'; -@Entity({ synchronize: true ,name: 'snowball_decoration' }) +@Entity({ synchronize: true, name: 'snowball_decoration' }) export class SnowballDecorationEntity { @PrimaryGeneratedColumn() id: number; @@ -18,7 +18,7 @@ export class SnowballDecorationEntity { @Column() decoration_id: number; - @Column({ length: 7}) + @Column({ length: 7 }) decoration_color: string; @Column() diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index a207142..461741d 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -13,7 +13,7 @@ import { UserEntity } from './user.entity'; import { SnowballDecorationEntity } from './snowball-decoration.entity'; import { MessageEntity } from '../../message/entity/message.entity'; -@Entity({ synchronize: true ,name: 'snowball' }) +@Entity({ synchronize: true, name: 'snowball' }) export class SnowballEntity { @PrimaryGeneratedColumn() id: number; diff --git a/back/src/modules/snowball/entity/user.entity.ts b/back/src/modules/snowball/entity/user.entity.ts index dbedafe..36ad8cc 100644 --- a/back/src/modules/snowball/entity/user.entity.ts +++ b/back/src/modules/snowball/entity/user.entity.ts @@ -7,7 +7,7 @@ import { } from 'typeorm'; import { SnowballEntity } from './snowball.entity'; -@Entity({synchronize: true , name: 'user' }) +@Entity({ synchronize: true, name: 'user' }) export class UserEntity { @PrimaryGeneratedColumn() id: number; From ad8ae74239c33279209dc7eaf8a5470c9283a6b6 Mon Sep 17 00:00:00 2001 From: peageon Date: Sun, 19 Nov 2023 21:18:37 +0900 Subject: [PATCH 036/185] =?UTF-8?q?feat:=20res-create-snowball.dto=20?= =?UTF-8?q?=EB=8D=94=20=EB=A7=8E=EC=9D=80=20=EA=B2=83=EB=93=A4=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=20=ED=95=98=EA=B2=8C=EB=81=94=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../snowball/dto/res-create-snowball.dto.ts | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/back/src/modules/snowball/dto/res-create-snowball.dto.ts b/back/src/modules/snowball/dto/res-create-snowball.dto.ts index 658a632..566ad20 100644 --- a/back/src/modules/snowball/dto/res-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/res-create-snowball.dto.ts @@ -1,11 +1,9 @@ +import { IsBoolean, ValidateNested } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -import { IsString, IsUUID } from 'class-validator'; +import { IsString, IsDate, IsUUID } from 'class-validator'; +import { DecorationSnowballDto } from './decoration-snowball.dto'; export class ResCreateSnowballDto { - @ApiProperty({ description: '스노우볼을 만든 유저의 id' }) - @IsUUID() - user_id: string; - @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) @IsUUID() snowball_uuid: string; @@ -13,4 +11,23 @@ export class ResCreateSnowballDto { @ApiProperty({ description: '생성된 스노우볼의 제목' }) @IsString() title: string; + + @ValidateNested({ each: true }) + @ApiProperty({ + type: [DecorationSnowballDto], + description: '데코오브젝트들이 들어있는 리스트' + }) + readonly deco_list: DecorationSnowballDto[]; + + @ApiProperty({ description: '메시지들의 공개 여부 (True이면 비공개)' }) + @IsBoolean() + message_private: boolean; + + @ApiProperty({ description: '받은 메시지 수 공개 여부 (True이면 비공개)' }) + @IsBoolean() + message_count_private: boolean; + + @ApiProperty({ description: '스노우볼이 언제 생성되었는지' }) + @IsDate() + createdAt: Date; } From 52d30dcc923eed6efa1c17c2158ac707d5a91b2f Mon Sep 17 00:00:00 2001 From: peageon Date: Sun, 19 Nov 2023 21:26:19 +0900 Subject: [PATCH 037/185] =?UTF-8?q?fix:=20snowball.controller=EC=97=90?= =?UTF-8?q?=EC=84=9C=20ResUpdateSnowballDto=EB=A5=BC=20swagger=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EB=9D=84=EC=96=B4=20=EC=A3=BC=EA=B2=8C=EB=81=94=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/snowball/snowball.controller.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index badb668..d424a58 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -10,6 +10,7 @@ import { import { CreateSnowballDto } from './dto/req-create-snowball.dto'; import { UpdateSnowballDto } from './dto/req-update-snowball.dto'; import { ResCreateSnowballDto } from './dto/res-create-snowball.dto'; +import { ResUpdateSnowballDto } from './dto/res-update-snowball.dto'; @ApiTags('Snowball API') @Controller('snowball') @@ -33,7 +34,8 @@ export class SnowballController { @Put() @ApiResponse({ status: 200, - description: '스노우볼 업데이트 성공' + description: '스노우볼 업데이트 성공', + type: ResUpdateSnowballDto }) @ApiOperation({ summary: '스노우볼 설정 업데이트 API', From a7085cc0cf7c1add1b9ce36d22e1f9a02ceed520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Mon, 20 Nov 2023 01:34:04 +0900 Subject: [PATCH 038/185] committing changes before rebase --- .github/workflows/FrontEnd.yml | 50 ++++++++++++++++++++++++++++++++++ .gitignore | 6 ++++ back/.gitignore | 37 ------------------------- package.json | 5 ++++ 4 files changed, 61 insertions(+), 37 deletions(-) create mode 100644 .github/workflows/FrontEnd.yml create mode 100644 .gitignore delete mode 100644 back/.gitignore create mode 100644 package.json diff --git a/.github/workflows/FrontEnd.yml b/.github/workflows/FrontEnd.yml new file mode 100644 index 0000000..012a66e --- /dev/null +++ b/.github/workflows/FrontEnd.yml @@ -0,0 +1,50 @@ +# This is a basic workflow to help you get started with Actions + +name: FrontEnd deploy + +# Controls when the workflow will run +on: + push: + branches: [ "FE/main" ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + build: + runs-on: ubuntu-latest + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v3 + + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '18' + + - name: Check Node v + run: node -v + + - name: Install dependencies + working-directory: ./front + run: npm install + + - name: Generate build + working-directory: ./front + run: npm run build + + - name: Deploy + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + run: | + aws s3 sync ./front/dist s3://snowball-ssock --region ap-northeast-2 --delete + + # 업로드한 s3 파일을 각 CDN 캐시 무효화하여 리프레시 하기 + - name: CloudFront Invalidation + env: + CLOUD_FRONT_ID: ${{ secrets.AWS_CLOUDFRONT_ID}} + run: | + aws cloudfront create-invalidation \ + --distribution-id $CLOUD_FRONT_ID --paths '/*' diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5599baf --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# compiled output +back/dist +/node_modules +back/node_modules +back/.env +back/test \ No newline at end of file diff --git a/back/.gitignore b/back/.gitignore deleted file mode 100644 index ea48d65..0000000 --- a/back/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -# compiled output -/dist -/node_modules - -# Logs -logs -*.log -npm-debug.log* -pnpm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# OS -.DS_Store - -# Tests -/coverage -/.nyc_output - -# IDEs and editors -/.idea -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace - -# IDE - VSCode -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json - -.env \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..7ed19b9 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@nestjs/class-validator": "^0.13.4" + } +} From 3ef3590db827c9f00ced3ef6fd34c5cec2d8bd71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Mon, 20 Nov 2023 01:44:46 +0900 Subject: [PATCH 039/185] =?UTF-8?q?fix:=20api=20=EB=AA=85=EC=84=B8?= =?UTF-8?q?=EC=99=80=20=EB=8B=A4=EB=A5=B8=20=EB=B6=80=EB=B6=84=EB=93=A4=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/config/ormconfig.ts | 3 ++- .../modules/message/entity/message.entity.ts | 6 ++--- .../snowball/dto/req-create-snowball.dto.ts | 4 +-- .../snowball/dto/req-update-snowball.dto.ts | 13 +++++----- .../snowball/dto/res-create-snowball.dto.ts | 26 +++---------------- .../snowball/dto/res-update-snowball.dto.ts | 2 +- .../entity/snowball-decoration.entity.ts | 4 +-- .../snowball/entity/snowball.entity.ts | 2 +- .../modules/snowball/entity/user.entity.ts | 3 +-- back/src/modules/snowball/snowball.service.ts | 2 +- 10 files changed, 23 insertions(+), 42 deletions(-) diff --git a/back/src/config/ormconfig.ts b/back/src/config/ormconfig.ts index a61ec16..11e9680 100644 --- a/back/src/config/ormconfig.ts +++ b/back/src/config/ormconfig.ts @@ -10,6 +10,7 @@ const typeOrmConfig: TypeOrmModuleOptions = { password: process.env.DATABASE_PASSWORD, database: process.env.DATABASE_SCHEMA, entities: [process.env.ENTITY_PATH], - synchronize: true + synchronize: true, + logging: true }; export default typeOrmConfig; diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 389e7a4..29957ee 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -8,7 +8,7 @@ import { } from 'typeorm'; import { SnowballEntity } from 'src/modules/snowball/entity/snowball.entity'; -@Entity({ synchronize: true ,name: 'message' }) +@Entity({ synchronize: true, name: 'message' }) export class MessageEntity { @PrimaryGeneratedColumn() id: number; @@ -19,13 +19,13 @@ export class MessageEntity { @Column() decoration_id: number; - @Column({ length: 7}) + @Column({ length: 7 }) decoration_color: string; @Column({ type: 'text' }) content: string; - @Column({ length: 16}) + @Column({ length: 16 }) sender: string; @CreateDateColumn({ nullable: true, default: null }) diff --git a/back/src/modules/snowball/dto/req-create-snowball.dto.ts b/back/src/modules/snowball/dto/req-create-snowball.dto.ts index a8b6c45..34e401c 100644 --- a/back/src/modules/snowball/dto/req-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/req-create-snowball.dto.ts @@ -31,7 +31,7 @@ export class CreateSnowballDto { @IsNotEmpty() @ApiProperty({ type: Boolean, - description: '스노우볼 속 메시지들 비공개 여부를 가리키는 불리언' + description: '스노우볼 속 메시지들 비공개 여부' }) readonly message_private: boolean; @@ -39,7 +39,7 @@ export class CreateSnowballDto { @IsNotEmpty() @ApiProperty({ type: Boolean, - description: '스노우볼 속 메시지 갯수의 비공개 여부를 가리키는 불리언' + description: '스노우볼 속 메시지 갯수의 비공개 여부' }) readonly message_count_private: boolean; } diff --git a/back/src/modules/snowball/dto/req-update-snowball.dto.ts b/back/src/modules/snowball/dto/req-update-snowball.dto.ts index 7831f09..0131269 100644 --- a/back/src/modules/snowball/dto/req-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/req-update-snowball.dto.ts @@ -1,16 +1,15 @@ import { IsString, - IsNumber, + IsUUID, IsNotEmpty, IsBoolean } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class UpdateSnowballDto { - @IsNumber() - @IsNotEmpty() - @ApiProperty({ type: Number, description: '유저의 id' }) - readonly user_id: number; + @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) + @IsUUID('4') + snowball_uuid: string; @IsString() @IsNotEmpty() @@ -21,7 +20,7 @@ export class UpdateSnowballDto { @IsNotEmpty() @ApiProperty({ type: Boolean, - description: '스노우볼 속 메시지들 비공개 여부를 가리키는 불리언' + description: '스노우볼 속 메시지들 비공개 여부' }) readonly message_private: boolean; @@ -29,7 +28,7 @@ export class UpdateSnowballDto { @IsNotEmpty() @ApiProperty({ type: Boolean, - description: '스노우볼 속 메시지 갯수의 비공개 여부를 가리키는 불리언' + description: '스노우볼 속 메시지 갯수 비공개 여부' }) readonly message_count_private: boolean; } diff --git a/back/src/modules/snowball/dto/res-create-snowball.dto.ts b/back/src/modules/snowball/dto/res-create-snowball.dto.ts index 566ad20..52a1886 100644 --- a/back/src/modules/snowball/dto/res-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/res-create-snowball.dto.ts @@ -1,33 +1,15 @@ -import { IsBoolean, ValidateNested } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; import { IsString, IsDate, IsUUID } from 'class-validator'; -import { DecorationSnowballDto } from './decoration-snowball.dto'; - export class ResCreateSnowballDto { @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) - @IsUUID() + @IsUUID('4') snowball_uuid: string; - @ApiProperty({ description: '생성된 스노우볼의 제목' }) + @ApiProperty({ description: '필터링된 스노우볼의 제목' }) @IsString() title: string; - @ValidateNested({ each: true }) - @ApiProperty({ - type: [DecorationSnowballDto], - description: '데코오브젝트들이 들어있는 리스트' - }) - readonly deco_list: DecorationSnowballDto[]; - - @ApiProperty({ description: '메시지들의 공개 여부 (True이면 비공개)' }) - @IsBoolean() - message_private: boolean; - - @ApiProperty({ description: '받은 메시지 수 공개 여부 (True이면 비공개)' }) - @IsBoolean() - message_count_private: boolean; - - @ApiProperty({ description: '스노우볼이 언제 생성되었는지' }) + @ApiProperty({ description: '스노우볼 생성 시간' }) @IsDate() - createdAt: Date; + created_at: Date; } diff --git a/back/src/modules/snowball/dto/res-update-snowball.dto.ts b/back/src/modules/snowball/dto/res-update-snowball.dto.ts index a2d6324..cc9b6ac 100644 --- a/back/src/modules/snowball/dto/res-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/res-update-snowball.dto.ts @@ -11,7 +11,7 @@ export class ResUpdateSnowballDto { readonly snowball_id: number; @IsString() - @ApiProperty({ type: String, description: '스노우볼 제목' }) + @ApiProperty({ type: String, description: '변경된 스노우볼 제목' }) readonly title: string; @IsBoolean() diff --git a/back/src/modules/snowball/entity/snowball-decoration.entity.ts b/back/src/modules/snowball/entity/snowball-decoration.entity.ts index c9d6429..d779663 100644 --- a/back/src/modules/snowball/entity/snowball-decoration.entity.ts +++ b/back/src/modules/snowball/entity/snowball-decoration.entity.ts @@ -7,7 +7,7 @@ import { } from 'typeorm'; import { SnowballEntity } from './snowball.entity'; -@Entity({ synchronize: true ,name: 'snowball_decoration' }) +@Entity({ name: 'snowball_decoration' }) export class SnowballDecorationEntity { @PrimaryGeneratedColumn() id: number; @@ -18,7 +18,7 @@ export class SnowballDecorationEntity { @Column() decoration_id: number; - @Column({ length: 7}) + @Column({ length: 7 }) decoration_color: string; @Column() diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index a207142..f72e71a 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -13,7 +13,7 @@ import { UserEntity } from './user.entity'; import { SnowballDecorationEntity } from './snowball-decoration.entity'; import { MessageEntity } from '../../message/entity/message.entity'; -@Entity({ synchronize: true ,name: 'snowball' }) +@Entity({ name: 'snowball' }) export class SnowballEntity { @PrimaryGeneratedColumn() id: number; diff --git a/back/src/modules/snowball/entity/user.entity.ts b/back/src/modules/snowball/entity/user.entity.ts index 29a5f48..b397bd7 100644 --- a/back/src/modules/snowball/entity/user.entity.ts +++ b/back/src/modules/snowball/entity/user.entity.ts @@ -7,8 +7,7 @@ import { } from 'typeorm'; import { SnowballEntity } from './snowball.entity'; - -@Entity({synchronize: true , name: 'user' }) +@Entity({ name: 'user' }) export class UserEntity { @PrimaryGeneratedColumn() id: number; diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 301dd3f..b304d07 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -18,6 +18,6 @@ export class SnowballService { return await this.snowballRepository.save(snowball); } async updateSnowball(updateSnowballDto: UpdateSnowballDto): Promise { - await this.snowballRepository.delete(updateSnowballDto.user_id); + await this.snowballRepository.delete(updateSnowballDto.snowball_uuid); } } From 82038ed86998784d30f7bccab1b448bbf2b9ec14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Mon, 20 Nov 2023 02:12:48 +0900 Subject: [PATCH 040/185] =?UTF-8?q?feat:=20message=20&=20update=20deco=20D?= =?UTF-8?q?TO=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/modules/auth/dto/main-snowball.dto.ts | 60 +++++++++++++++++++ back/src/modules/auth/dto/message.dto.ts | 36 +++++++++++ back/src/modules/auth/dto/res-info.dto.ts | 41 +++++++++++++ back/src/modules/auth/dto/user.dto.ts | 37 ++++++++++++ ...ssage.dto.ts => req-create-message.dto.ts} | 3 +- ...ssage.dto.ts => req-delete-message.dto.ts} | 0 .../message/dto/res-create-message.dto.ts | 17 ++++++ .../src/modules/message/message.controller.ts | 4 +- back/src/modules/message/message.service.ts | 4 +- .../snowball/dto/req-create-snowball.dto.ts | 8 ++- .../snowball/dto/req-update-decoration.dto.ts | 25 ++++++++ .../snowball/dto/res-create-snowball.dto.ts | 2 +- .../snowball/dto/res-update-decoration.dto.ts | 25 ++++++++ .../snowball/dto/res-update-snowball.dto.ts | 4 +- 14 files changed, 256 insertions(+), 10 deletions(-) create mode 100644 back/src/modules/auth/dto/main-snowball.dto.ts create mode 100644 back/src/modules/auth/dto/message.dto.ts create mode 100644 back/src/modules/auth/dto/res-info.dto.ts create mode 100644 back/src/modules/auth/dto/user.dto.ts rename back/src/modules/message/dto/{create-message.dto.ts => req-create-message.dto.ts} (93%) rename back/src/modules/message/dto/{delete-message.dto.ts => req-delete-message.dto.ts} (100%) create mode 100644 back/src/modules/message/dto/res-create-message.dto.ts create mode 100644 back/src/modules/snowball/dto/req-update-decoration.dto.ts create mode 100644 back/src/modules/snowball/dto/res-update-decoration.dto.ts diff --git a/back/src/modules/auth/dto/main-snowball.dto.ts b/back/src/modules/auth/dto/main-snowball.dto.ts new file mode 100644 index 0000000..e42745e --- /dev/null +++ b/back/src/modules/auth/dto/main-snowball.dto.ts @@ -0,0 +1,60 @@ +import { + IsString, + IsUUID, + IsBoolean, + IsNotEmpty, + IsArray, + ValidateNested +} from '@nestjs/class-validator'; +import { Type } from '@nestjs/class-transformer'; +import { ApiProperty } from '@nestjs/swagger'; +import { DecorationSnowballDto } from '../../snowball/dto/decoration-snowball.dto'; +import { MessageDto } from './message.dto'; + +export class MainSnowballDto { + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '스노우볼 제목' }) + readonly title: string; + + @IsUUID('4') + @IsNotEmpty() + @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) + readonly uuid: string; + + @IsBoolean() + @IsNotEmpty() + @ApiProperty({ + type: Boolean, + description: '스노우볼 속 메시지들 비공개 여부' + }) + readonly message_private: boolean; + + @IsBoolean() + @IsNotEmpty() + @ApiProperty({ + type: Boolean, + description: '스노우볼 속 메시지 갯수 비공개 여부' + }) + readonly message_count_private: boolean; + + @IsNotEmpty() + @IsArray() + @ValidateNested({ each: true }) + @Type(() => DecorationSnowballDto) + @ApiProperty({ + type: [DecorationSnowballDto], + description: '데코오브젝트들이 들어있는 리스트' + }) + readonly deco_list: DecorationSnowballDto[]; + + @IsNotEmpty() + @IsArray() + @ValidateNested({ each: true }) + @Type(() => MessageDto) + @ApiProperty({ + type: [MessageDto], + description: '스노우볼 속 메시지 리스트' + }) + readonly message_list: MessageDto[]; +} diff --git a/back/src/modules/auth/dto/message.dto.ts b/back/src/modules/auth/dto/message.dto.ts new file mode 100644 index 0000000..aff438b --- /dev/null +++ b/back/src/modules/auth/dto/message.dto.ts @@ -0,0 +1,36 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsString, IsNumber, IsDate } from 'class-validator'; + +export class MessageDto { + @IsNumber() + @ApiProperty({ type: Number, description: '메시지 ID' }) + readonly id: number; + + @IsString() + @ApiProperty({ type: String, description: '스노우볼 ID' }) + readonly snowball_id: string; + + @IsNumber() + @ApiProperty({ type: Number, description: '데코레이션 ID' }) + readonly decoration_id: number; + + @IsString() + @ApiProperty({ type: String, description: '데코레이션 색상' }) + readonly decoration_color: string; + + @IsString() + @ApiProperty({ type: String, description: '메시지 내용' }) + readonly content: string; + + @IsString() + @ApiProperty({ type: String, description: '보낸이' }) + readonly sender: string; + + @IsDate() + @ApiProperty({ type: Date, description: '열린 날짜' }) + readonly opened: Date | null; + + @IsDate() + @ApiProperty({ type: Date, description: '생성 날짜' }) + readonly created_at: Date; +} diff --git a/back/src/modules/auth/dto/res-info.dto.ts b/back/src/modules/auth/dto/res-info.dto.ts new file mode 100644 index 0000000..5569c18 --- /dev/null +++ b/back/src/modules/auth/dto/res-info.dto.ts @@ -0,0 +1,41 @@ +import { + IsString, + IsNotEmpty, + ValidateNested, + IsArray +} from '@nestjs/class-validator'; +import { ApiProperty } from '@nestjs/swagger'; +import { UserDto } from './user.dto'; +import { MainSnowballDto } from './main-snowball.dto'; +import { Type } from '@nestjs/class-transformer'; + +export class InfoDto { + @IsNotEmpty() + @IsString() + @ApiProperty({ + type: String, + description: 'Bearer 타입의 OAuth 2.0 액세스 토큰', + example: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' + }) + readonly access_token: string; + + @IsNotEmpty() + @IsArray() + @ValidateNested({ each: true }) + @Type(() => UserDto) + @ApiProperty({ + type: UserDto, + description: '사용자 정보 배열' + }) + readonly user: UserDto[]; + + @IsNotEmpty() + @IsArray() + @ValidateNested({ each: true }) + @Type(() => MainSnowballDto) + @ApiProperty({ + type: MainSnowballDto, + description: '메인 스노우볼 정보 배열' + }) + readonly main_snowball: MainSnowballDto[]; +} diff --git a/back/src/modules/auth/dto/user.dto.ts b/back/src/modules/auth/dto/user.dto.ts new file mode 100644 index 0000000..67d0b1c --- /dev/null +++ b/back/src/modules/auth/dto/user.dto.ts @@ -0,0 +1,37 @@ +import { + IsString, + IsNumber, + IsUUID, + IsNotEmpty +} from '@nestjs/class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class UserDto { + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '사용자 이름' }) + readonly name: string; + + @IsUUID('4') + @IsNotEmpty() + @ApiProperty({ format: 'uuid', description: 'Oauth에서 주는 값' }) + readonly id: string; + + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '스노우볼 갯수' }) + readonly snowball_count: number; + + @IsNotEmpty() + @ApiProperty({ + type: [String], + format: 'uuid', + description: '스노우볼 UUID 리스트' + }) + readonly snowball_list: string[]; + + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '메시지 갯수' }) + readonly message_count: number; +} diff --git a/back/src/modules/message/dto/create-message.dto.ts b/back/src/modules/message/dto/req-create-message.dto.ts similarity index 93% rename from back/src/modules/message/dto/create-message.dto.ts rename to back/src/modules/message/dto/req-create-message.dto.ts index 45d1270..b6520ae 100644 --- a/back/src/modules/message/dto/create-message.dto.ts +++ b/back/src/modules/message/dto/req-create-message.dto.ts @@ -1,9 +1,10 @@ import { IsString, IsNotEmpty, IsNumber } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; +import { IsUUID } from 'class-validator'; export class CreateMessageDto { @IsNotEmpty() - @IsString() + @IsUUID('4') @ApiProperty({ type: String, description: '스노우볼 uuid' }) readonly snowball_id: string; diff --git a/back/src/modules/message/dto/delete-message.dto.ts b/back/src/modules/message/dto/req-delete-message.dto.ts similarity index 100% rename from back/src/modules/message/dto/delete-message.dto.ts rename to back/src/modules/message/dto/req-delete-message.dto.ts diff --git a/back/src/modules/message/dto/res-create-message.dto.ts b/back/src/modules/message/dto/res-create-message.dto.ts new file mode 100644 index 0000000..18ee020 --- /dev/null +++ b/back/src/modules/message/dto/res-create-message.dto.ts @@ -0,0 +1,17 @@ +import { IsString, IsNotEmpty } from '@nestjs/class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class CreateMessageDto { + @IsString() + @IsNotEmpty() + @ApiProperty({ + type: String, + description: '필터링된 익명 사용자 닉네임(From)' + }) + readonly sender: string; + + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '필터링된 메세지 내용' }) + readonly content: string; +} diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index ae491b5..b728e2d 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -1,7 +1,7 @@ import { Controller, Post, Delete, Body, Param } from '@nestjs/common'; import { MessageService } from './message.service'; -import { CreateMessageDto } from './dto/create-message.dto'; -import { DeleteMessageDto } from './dto/delete-message.dto'; +import { CreateMessageDto } from './dto/req-create-message.dto'; +import { DeleteMessageDto } from './dto/req-delete-message.dto'; import { ApiBody, ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; @ApiTags('Message API') diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 35c6138..a62b7dc 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { CreateMessageDto } from './dto/create-message.dto'; -import { DeleteMessageDto } from './dto/delete-message.dto'; +import { CreateMessageDto } from './dto/req-create-message.dto'; +import { DeleteMessageDto } from './dto/req-delete-message.dto'; import { MessageEntity } from './entity/message.entity'; @Injectable() diff --git a/back/src/modules/snowball/dto/req-create-snowball.dto.ts b/back/src/modules/snowball/dto/req-create-snowball.dto.ts index 34e401c..31b480c 100644 --- a/back/src/modules/snowball/dto/req-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/req-create-snowball.dto.ts @@ -3,17 +3,21 @@ import { IsNumber, IsNotEmpty, IsBoolean, + IsArray, ValidateNested } from '@nestjs/class-validator'; +import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; import { DecorationSnowballDto } from './decoration-snowball.dto'; export class CreateSnowballDto { @IsNotEmpty() + @IsArray() @ValidateNested({ each: true }) + @Type(() => DecorationSnowballDto) @ApiProperty({ type: [DecorationSnowballDto], - description: '데코오브젝트들이 들어있는 리스트' + description: '데코오브젝트들이 들어있는 배열' }) readonly deco_list: DecorationSnowballDto[]; @@ -39,7 +43,7 @@ export class CreateSnowballDto { @IsNotEmpty() @ApiProperty({ type: Boolean, - description: '스노우볼 속 메시지 갯수의 비공개 여부' + description: '스노우볼 속 메시지 갯수 비공개 여부' }) readonly message_count_private: boolean; } diff --git a/back/src/modules/snowball/dto/req-update-decoration.dto.ts b/back/src/modules/snowball/dto/req-update-decoration.dto.ts new file mode 100644 index 0000000..97ea2ed --- /dev/null +++ b/back/src/modules/snowball/dto/req-update-decoration.dto.ts @@ -0,0 +1,25 @@ +import { + IsUUID, + IsNotEmpty, + ValidateNested, + IsArray +} from '@nestjs/class-validator'; +import { Type } from '@nestjs/class-transformer'; +import { ApiProperty } from '@nestjs/swagger'; +import { DecorationSnowballDto } from './decoration-snowball.dto'; + +export class UpdateSnowballDto { + @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) + @IsUUID('4') + snowball_uuid: string; + + @IsNotEmpty() + @IsArray() + @ValidateNested({ each: true }) + @Type(() => DecorationSnowballDto) + @ApiProperty({ + type: [DecorationSnowballDto], + description: '데코오브젝트들이 들어있는 배열' + }) + readonly deco_list: DecorationSnowballDto[]; +} diff --git a/back/src/modules/snowball/dto/res-create-snowball.dto.ts b/back/src/modules/snowball/dto/res-create-snowball.dto.ts index 52a1886..8b8945b 100644 --- a/back/src/modules/snowball/dto/res-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/res-create-snowball.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsString, IsDate, IsUUID } from 'class-validator'; export class ResCreateSnowballDto { - @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) + @ApiProperty({ format: 'uuid', description: '변경된 스노우볼 UUID' }) @IsUUID('4') snowball_uuid: string; diff --git a/back/src/modules/snowball/dto/res-update-decoration.dto.ts b/back/src/modules/snowball/dto/res-update-decoration.dto.ts new file mode 100644 index 0000000..1dbb90b --- /dev/null +++ b/back/src/modules/snowball/dto/res-update-decoration.dto.ts @@ -0,0 +1,25 @@ +import { + IsUUID, + IsNotEmpty, + ValidateNested, + IsArray +} from '@nestjs/class-validator'; +import { Type } from '@nestjs/class-transformer'; +import { ApiProperty } from '@nestjs/swagger'; +import { DecorationSnowballDto } from './decoration-snowball.dto'; + +export class UpdateSnowballDto { + @ApiProperty({ format: 'uuid', description: '변경된 스노우볼 UUID' }) + @IsUUID('4') + snowball_uuid: string; + + @IsNotEmpty() + @IsArray() + @ValidateNested({ each: true }) + @Type(() => DecorationSnowballDto) + @ApiProperty({ + type: [DecorationSnowballDto], + description: '변경된 데코오브젝트들이 들어있는 배열' + }) + readonly deco_list: DecorationSnowballDto[]; +} diff --git a/back/src/modules/snowball/dto/res-update-snowball.dto.ts b/back/src/modules/snowball/dto/res-update-snowball.dto.ts index cc9b6ac..25d8e63 100644 --- a/back/src/modules/snowball/dto/res-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/res-update-snowball.dto.ts @@ -17,14 +17,14 @@ export class ResUpdateSnowballDto { @IsBoolean() @ApiProperty({ type: Boolean, - description: '메시지들의 공개 여부 (True이면 비공개)' + description: '변경된 스노우볼 속 메시지들 비공개 여부' }) readonly message_private: boolean; @IsBoolean() @ApiProperty({ type: Boolean, - description: '받은 메시지 수 공개 여부 (True이면 비공개)' + description: '변경된 스노우볼 속 메시지 갯수 비공개 여부' }) readonly message_count_private: boolean; } From b42b589a662d833ec13e07360418e4a7d6dcbb58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Mon, 20 Nov 2023 02:27:35 +0900 Subject: [PATCH 041/185] =?UTF-8?q?feat:=20dto=20=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20=EC=9E=90?= =?UTF-8?q?=EC=9E=98=ED=95=9C=20=EB=B3=80=EA=B2=BD=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/dto/{ => response}/res-info.dto.ts | 21 +++++++------------ .../{auth => message}/dto/message.dto.ts | 0 .../{ => request}/req-create-message.dto.ts | 2 +- .../{ => request}/req-delete-message.dto.ts | 2 +- .../{ => response}/res-create-message.dto.ts | 2 +- .../src/modules/message/message.controller.ts | 4 ++-- back/src/modules/message/message.service.ts | 4 ++-- .../{ => request}/req-create-snowball.dto.ts | 6 ++---- .../req-update-decoration.dto.ts | 10 ++------- .../{ => request}/req-update-snowball.dto.ts | 2 +- .../{ => response}/res-create-snowball.dto.ts | 0 .../res-update-decoration.dto.ts | 10 ++------- .../{ => response}/res-update-snowball.dto.ts | 0 .../dto/snowball.dto.ts} | 7 ++----- .../modules/snowball/snowball.controller.ts | 16 +++++++------- back/src/modules/snowball/snowball.service.ts | 8 +++---- 16 files changed, 35 insertions(+), 59 deletions(-) rename back/src/modules/auth/dto/{ => response}/res-info.dto.ts (65%) rename back/src/modules/{auth => message}/dto/message.dto.ts (100%) rename back/src/modules/message/dto/{ => request}/req-create-message.dto.ts (96%) rename back/src/modules/message/dto/{ => request}/req-delete-message.dto.ts (87%) rename back/src/modules/message/dto/{ => response}/res-create-message.dto.ts (92%) rename back/src/modules/snowball/dto/{ => request}/req-create-snowball.dto.ts (89%) rename back/src/modules/snowball/dto/{ => request}/req-update-decoration.dto.ts (79%) rename back/src/modules/snowball/dto/{ => request}/req-update-snowball.dto.ts (95%) rename back/src/modules/snowball/dto/{ => response}/res-create-snowball.dto.ts (100%) rename back/src/modules/snowball/dto/{ => response}/res-update-decoration.dto.ts (79%) rename back/src/modules/snowball/dto/{ => response}/res-update-snowball.dto.ts (100%) rename back/src/modules/{auth/dto/main-snowball.dto.ts => snowball/dto/snowball.dto.ts} (92%) diff --git a/back/src/modules/auth/dto/res-info.dto.ts b/back/src/modules/auth/dto/response/res-info.dto.ts similarity index 65% rename from back/src/modules/auth/dto/res-info.dto.ts rename to back/src/modules/auth/dto/response/res-info.dto.ts index 5569c18..44bb941 100644 --- a/back/src/modules/auth/dto/res-info.dto.ts +++ b/back/src/modules/auth/dto/response/res-info.dto.ts @@ -1,15 +1,10 @@ -import { - IsString, - IsNotEmpty, - ValidateNested, - IsArray -} from '@nestjs/class-validator'; +import { IsString, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -import { UserDto } from './user.dto'; -import { MainSnowballDto } from './main-snowball.dto'; +import { UserDto } from '../user.dto'; +import { SnowballDto } from '../../../snowball/dto/snowball.dto'; import { Type } from '@nestjs/class-transformer'; -export class InfoDto { +export class ResInfoDto { @IsNotEmpty() @IsString() @ApiProperty({ @@ -20,7 +15,6 @@ export class InfoDto { readonly access_token: string; @IsNotEmpty() - @IsArray() @ValidateNested({ each: true }) @Type(() => UserDto) @ApiProperty({ @@ -30,12 +24,11 @@ export class InfoDto { readonly user: UserDto[]; @IsNotEmpty() - @IsArray() @ValidateNested({ each: true }) - @Type(() => MainSnowballDto) + @Type(() => SnowballDto) @ApiProperty({ - type: MainSnowballDto, + type: SnowballDto, description: '메인 스노우볼 정보 배열' }) - readonly main_snowball: MainSnowballDto[]; + readonly main_snowball: SnowballDto[]; } diff --git a/back/src/modules/auth/dto/message.dto.ts b/back/src/modules/message/dto/message.dto.ts similarity index 100% rename from back/src/modules/auth/dto/message.dto.ts rename to back/src/modules/message/dto/message.dto.ts diff --git a/back/src/modules/message/dto/req-create-message.dto.ts b/back/src/modules/message/dto/request/req-create-message.dto.ts similarity index 96% rename from back/src/modules/message/dto/req-create-message.dto.ts rename to back/src/modules/message/dto/request/req-create-message.dto.ts index b6520ae..1b995b5 100644 --- a/back/src/modules/message/dto/req-create-message.dto.ts +++ b/back/src/modules/message/dto/request/req-create-message.dto.ts @@ -2,7 +2,7 @@ import { IsString, IsNotEmpty, IsNumber } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; import { IsUUID } from 'class-validator'; -export class CreateMessageDto { +export class ReqCreateMessageDto { @IsNotEmpty() @IsUUID('4') @ApiProperty({ type: String, description: '스노우볼 uuid' }) diff --git a/back/src/modules/message/dto/req-delete-message.dto.ts b/back/src/modules/message/dto/request/req-delete-message.dto.ts similarity index 87% rename from back/src/modules/message/dto/req-delete-message.dto.ts rename to back/src/modules/message/dto/request/req-delete-message.dto.ts index 62b48aa..82f2662 100644 --- a/back/src/modules/message/dto/req-delete-message.dto.ts +++ b/back/src/modules/message/dto/request/req-delete-message.dto.ts @@ -1,7 +1,7 @@ import { IsNumber, IsNotEmpty } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -export class DeleteMessageDto { +export class ReqDeleteMessageDto { @IsNumber() @IsNotEmpty() @ApiProperty({ type: Number, description: '메세지 id' }) diff --git a/back/src/modules/message/dto/res-create-message.dto.ts b/back/src/modules/message/dto/response/res-create-message.dto.ts similarity index 92% rename from back/src/modules/message/dto/res-create-message.dto.ts rename to back/src/modules/message/dto/response/res-create-message.dto.ts index 18ee020..4e3931c 100644 --- a/back/src/modules/message/dto/res-create-message.dto.ts +++ b/back/src/modules/message/dto/response/res-create-message.dto.ts @@ -1,7 +1,7 @@ import { IsString, IsNotEmpty } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -export class CreateMessageDto { +export class ResCreateMessageDto { @IsString() @IsNotEmpty() @ApiProperty({ diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index b728e2d..b36abe8 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -1,7 +1,7 @@ import { Controller, Post, Delete, Body, Param } from '@nestjs/common'; import { MessageService } from './message.service'; -import { CreateMessageDto } from './dto/req-create-message.dto'; -import { DeleteMessageDto } from './dto/req-delete-message.dto'; +import { CreateMessageDto } from './dto/request/req-create-message.dto'; +import { DeleteMessageDto } from './dto/request/req-delete-message.dto'; import { ApiBody, ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; @ApiTags('Message API') diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index a62b7dc..096dc17 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { CreateMessageDto } from './dto/req-create-message.dto'; -import { DeleteMessageDto } from './dto/req-delete-message.dto'; +import { CreateMessageDto } from './dto/request/req-create-message.dto'; +import { DeleteMessageDto } from './dto/request/req-delete-message.dto'; import { MessageEntity } from './entity/message.entity'; @Injectable() diff --git a/back/src/modules/snowball/dto/req-create-snowball.dto.ts b/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts similarity index 89% rename from back/src/modules/snowball/dto/req-create-snowball.dto.ts rename to back/src/modules/snowball/dto/request/req-create-snowball.dto.ts index 31b480c..e3d9267 100644 --- a/back/src/modules/snowball/dto/req-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts @@ -3,16 +3,14 @@ import { IsNumber, IsNotEmpty, IsBoolean, - IsArray, ValidateNested } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; -import { DecorationSnowballDto } from './decoration-snowball.dto'; +import { DecorationSnowballDto } from '../decoration-snowball.dto'; -export class CreateSnowballDto { +export class ReqCreateSnowballDto { @IsNotEmpty() - @IsArray() @ValidateNested({ each: true }) @Type(() => DecorationSnowballDto) @ApiProperty({ diff --git a/back/src/modules/snowball/dto/req-update-decoration.dto.ts b/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts similarity index 79% rename from back/src/modules/snowball/dto/req-update-decoration.dto.ts rename to back/src/modules/snowball/dto/request/req-update-decoration.dto.ts index 97ea2ed..9c33e84 100644 --- a/back/src/modules/snowball/dto/req-update-decoration.dto.ts +++ b/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts @@ -1,20 +1,14 @@ -import { - IsUUID, - IsNotEmpty, - ValidateNested, - IsArray -} from '@nestjs/class-validator'; +import { IsUUID, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; import { DecorationSnowballDto } from './decoration-snowball.dto'; -export class UpdateSnowballDto { +export class ReqUpdateSnowballDecoDto { @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) @IsUUID('4') snowball_uuid: string; @IsNotEmpty() - @IsArray() @ValidateNested({ each: true }) @Type(() => DecorationSnowballDto) @ApiProperty({ diff --git a/back/src/modules/snowball/dto/req-update-snowball.dto.ts b/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts similarity index 95% rename from back/src/modules/snowball/dto/req-update-snowball.dto.ts rename to back/src/modules/snowball/dto/request/req-update-snowball.dto.ts index 0131269..f790222 100644 --- a/back/src/modules/snowball/dto/req-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts @@ -6,7 +6,7 @@ import { } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -export class UpdateSnowballDto { +export class ReqUpdateSnowballDto { @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) @IsUUID('4') snowball_uuid: string; diff --git a/back/src/modules/snowball/dto/res-create-snowball.dto.ts b/back/src/modules/snowball/dto/response/res-create-snowball.dto.ts similarity index 100% rename from back/src/modules/snowball/dto/res-create-snowball.dto.ts rename to back/src/modules/snowball/dto/response/res-create-snowball.dto.ts diff --git a/back/src/modules/snowball/dto/res-update-decoration.dto.ts b/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts similarity index 79% rename from back/src/modules/snowball/dto/res-update-decoration.dto.ts rename to back/src/modules/snowball/dto/response/res-update-decoration.dto.ts index 1dbb90b..5673a9b 100644 --- a/back/src/modules/snowball/dto/res-update-decoration.dto.ts +++ b/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts @@ -1,20 +1,14 @@ -import { - IsUUID, - IsNotEmpty, - ValidateNested, - IsArray -} from '@nestjs/class-validator'; +import { IsUUID, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; import { DecorationSnowballDto } from './decoration-snowball.dto'; -export class UpdateSnowballDto { +export class ResUpdateSnowballDto { @ApiProperty({ format: 'uuid', description: '변경된 스노우볼 UUID' }) @IsUUID('4') snowball_uuid: string; @IsNotEmpty() - @IsArray() @ValidateNested({ each: true }) @Type(() => DecorationSnowballDto) @ApiProperty({ diff --git a/back/src/modules/snowball/dto/res-update-snowball.dto.ts b/back/src/modules/snowball/dto/response/res-update-snowball.dto.ts similarity index 100% rename from back/src/modules/snowball/dto/res-update-snowball.dto.ts rename to back/src/modules/snowball/dto/response/res-update-snowball.dto.ts diff --git a/back/src/modules/auth/dto/main-snowball.dto.ts b/back/src/modules/snowball/dto/snowball.dto.ts similarity index 92% rename from back/src/modules/auth/dto/main-snowball.dto.ts rename to back/src/modules/snowball/dto/snowball.dto.ts index e42745e..d66802f 100644 --- a/back/src/modules/auth/dto/main-snowball.dto.ts +++ b/back/src/modules/snowball/dto/snowball.dto.ts @@ -3,15 +3,14 @@ import { IsUUID, IsBoolean, IsNotEmpty, - IsArray, ValidateNested } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; import { DecorationSnowballDto } from '../../snowball/dto/decoration-snowball.dto'; -import { MessageDto } from './message.dto'; +import { MessageDto } from '../../message/dto/message.dto'; -export class MainSnowballDto { +export class SnowballDto { @IsString() @IsNotEmpty() @ApiProperty({ type: String, description: '스노우볼 제목' }) @@ -39,7 +38,6 @@ export class MainSnowballDto { readonly message_count_private: boolean; @IsNotEmpty() - @IsArray() @ValidateNested({ each: true }) @Type(() => DecorationSnowballDto) @ApiProperty({ @@ -49,7 +47,6 @@ export class MainSnowballDto { readonly deco_list: DecorationSnowballDto[]; @IsNotEmpty() - @IsArray() @ValidateNested({ each: true }) @Type(() => MessageDto) @ApiProperty({ diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index d424a58..4a403fb 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -7,10 +7,10 @@ import { ApiCreatedResponse, ApiResponse } from '@nestjs/swagger'; -import { CreateSnowballDto } from './dto/req-create-snowball.dto'; -import { UpdateSnowballDto } from './dto/req-update-snowball.dto'; -import { ResCreateSnowballDto } from './dto/res-create-snowball.dto'; -import { ResUpdateSnowballDto } from './dto/res-update-snowball.dto'; +import { ReqCreateSnowballDto } from './dto/request/req-create-snowball.dto'; +import { ReqUpdateSnowballDto } from './dto/request/req-update-snowball.dto'; +import { ResCreateSnowballDto } from './dto/response/res-create-snowball.dto'; +import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; @ApiTags('Snowball API') @Controller('snowball') @@ -26,8 +26,8 @@ export class SnowballController { description: '스노우볼 생성 성공', type: ResCreateSnowballDto }) - @ApiBody({ type: CreateSnowballDto }) - createSnowball(@Body() createSnowballDto: CreateSnowballDto) { + @ApiBody({ type: ReqCreateSnowballDto }) + createSnowball(@Body() createSnowballDto: ReqCreateSnowballDto) { return createSnowballDto; } @@ -41,8 +41,8 @@ export class SnowballController { summary: '스노우볼 설정 업데이트 API', description: '스노우볼에의 정보를 업데이트 해줍니다.' }) - @ApiBody({ type: UpdateSnowballDto }) - updateSnowball(@Body() updateSnowballDto: UpdateSnowballDto) { + @ApiBody({ type: ReqUpdateSnowballDto }) + updateSnowball(@Body() updateSnowballDto: ReqUpdateSnowballDto) { updateSnowballDto; } } diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index b304d07..79e4f98 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { SnowballEntity } from './entity/snowball.entity'; -import { CreateSnowballDto } from './dto/req-create-snowball.dto'; -import { UpdateSnowballDto } from './dto/req-update-snowball.dto'; +import { ReqCreateSnowballDto } from './dto/request/req-create-snowball.dto'; +import { ReqUpdateSnowballDto } from './dto/request/req-update-snowball.dto'; @Injectable() export class SnowballService { @@ -12,12 +12,12 @@ export class SnowballService { private readonly snowballRepository: Repository ) {} async createSnowball( - createSnowballDto: CreateSnowballDto + createSnowballDto: ReqCreateSnowballDto ): Promise { const snowball = this.snowballRepository.create(createSnowballDto); return await this.snowballRepository.save(snowball); } - async updateSnowball(updateSnowballDto: UpdateSnowballDto): Promise { + async updateSnowball(updateSnowballDto: ReqUpdateSnowballDto): Promise { await this.snowballRepository.delete(updateSnowballDto.snowball_uuid); } } From 06ad6ffc31ea8997adb22d2eb461944c934ef649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Mon, 20 Nov 2023 02:44:15 +0900 Subject: [PATCH 042/185] =?UTF-8?q?fix:=20=ED=8C=8C=EC=9D=BC=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.controller.ts | 12 ++++++------ back/src/modules/message/message.service.ts | 8 ++++---- .../dto/request/req-update-decoration.dto.ts | 2 +- .../dto/response/res-update-decoration.dto.ts | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index b36abe8..1179cbd 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -1,7 +1,7 @@ import { Controller, Post, Delete, Body, Param } from '@nestjs/common'; import { MessageService } from './message.service'; -import { CreateMessageDto } from './dto/request/req-create-message.dto'; -import { DeleteMessageDto } from './dto/request/req-delete-message.dto'; +import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; +import { ReqDeleteMessageDto } from './dto/request/req-delete-message.dto'; import { ApiBody, ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; @ApiTags('Message API') @@ -14,9 +14,9 @@ export class MessageController { summary: '메세지 생성 API', description: '스노우볼에 메세지를 생성합니다.' }) - @ApiBody({ type: CreateMessageDto }) + @ApiBody({ type: ReqCreateMessageDto }) @ApiResponse({ status: 201, description: 'Created' }) - createMessage(@Body() createMessageDto: CreateMessageDto) { + createMessage(@Body() createMessageDto: ReqCreateMessageDto) { return this.messageService.createMessage(createMessageDto); } @@ -25,9 +25,9 @@ export class MessageController { summary: '메세지 삭제 API', description: '스노우볼에서 특정 메세지를 삭제합니다.' }) - @ApiBody({ type: DeleteMessageDto }) + @ApiBody({ type: ReqDeleteMessageDto }) @ApiResponse({ status: 204, description: 'No Content' }) - deleteMessage(@Param() deleteMessageDto: DeleteMessageDto) { + deleteMessage(@Param() deleteMessageDto: ReqDeleteMessageDto) { this.messageService.deleteMessage(deleteMessageDto); } } diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 096dc17..a95efee 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { CreateMessageDto } from './dto/request/req-create-message.dto'; -import { DeleteMessageDto } from './dto/request/req-delete-message.dto'; +import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; +import { ReqDeleteMessageDto } from './dto/request/req-delete-message.dto'; import { MessageEntity } from './entity/message.entity'; @Injectable() @@ -12,7 +12,7 @@ export class MessageService { private readonly messageRepository: Repository ) {} async createMessage( - createMessageDto: CreateMessageDto + createMessageDto: ReqCreateMessageDto ): Promise { const messageEntity = this.messageRepository.create({ snowball_id: createMessageDto.snowball_id, @@ -23,7 +23,7 @@ export class MessageService { }); return await this.messageRepository.save(messageEntity); } - async deleteMessage(deleteMessageDto: DeleteMessageDto): Promise { + async deleteMessage(deleteMessageDto: ReqDeleteMessageDto): Promise { await this.messageRepository.delete(deleteMessageDto.message_id); } diff --git a/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts b/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts index 9c33e84..88f18a3 100644 --- a/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts +++ b/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts @@ -1,7 +1,7 @@ import { IsUUID, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; -import { DecorationSnowballDto } from './decoration-snowball.dto'; +import { DecorationSnowballDto } from '../decoration-snowball.dto'; export class ReqUpdateSnowballDecoDto { @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) diff --git a/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts b/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts index 5673a9b..c212a94 100644 --- a/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts +++ b/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts @@ -1,9 +1,9 @@ import { IsUUID, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; -import { DecorationSnowballDto } from './decoration-snowball.dto'; +import { DecorationSnowballDto } from '../decoration-snowball.dto'; -export class ResUpdateSnowballDto { +export class ResUpdateSnowballDecoDto { @ApiProperty({ format: 'uuid', description: '변경된 스노우볼 UUID' }) @IsUUID('4') snowball_uuid: string; From a1870328365a7dda9660c5b1fdefa926e30747b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Mon, 20 Nov 2023 03:29:15 +0900 Subject: [PATCH 043/185] =?UTF-8?q?feat:=20auth=20api=20response=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/app.module.ts | 3 +- back/src/modules/auth/auth.controller.ts | 67 +++++++++++------ back/src/modules/auth/auth.module.ts | 8 +- back/src/modules/auth/auth.service.ts | 74 +++++++++++++++++++ back/src/modules/message/dto/message.dto.ts | 6 +- .../snowball/dto/decoration-snowball.dto.ts | 2 +- 6 files changed, 127 insertions(+), 33 deletions(-) create mode 100644 back/src/modules/auth/auth.service.ts diff --git a/back/src/app.module.ts b/back/src/app.module.ts index 2dfd366..a72e16d 100644 --- a/back/src/app.module.ts +++ b/back/src/app.module.ts @@ -2,14 +2,13 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { AppController } from './app.controller'; import { AppService } from './app.service'; -import { AuthController } from './modules/auth/auth.controller'; import { AuthModule } from './modules/auth/auth.module'; import { SnowballModule } from './modules/snowball/snowball.module'; import typeOrmConfig from './config/ormconfig'; @Module({ imports: [TypeOrmModule.forRoot(typeOrmConfig), AuthModule, SnowballModule], - controllers: [AppController, AuthController], + controllers: [AppController], providers: [AppService] }) export class AppModule {} diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index a0a9bf1..3c7215f 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -1,15 +1,13 @@ import { Controller, Get, Req, Res, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; -import { - ApiTags, - ApiOperation, - ApiExcludeEndpoint, - ApiResponse -} from '@nestjs/swagger'; +import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; +import { ResInfoDto } from './dto/response/res-info.dto'; +import { AuthService } from './auth.service'; @ApiTags('Oauth API') @Controller('auth') export class AuthController { + constructor(private readonly authService: AuthService) {} @Get('google') @ApiOperation({ summary: 'Google 로그인 요청 API', @@ -17,23 +15,30 @@ export class AuthController { }) @ApiResponse({ status: 200, - description: `'https://mysnowball.kr'로 리다이렉트` + description: `'https://mysnowball.kr/auth/google/redirect'로 GET요청을 보냅니다.` }) @ApiResponse({ status: 400, - description: `'https://mysnowball.kr/failure'으로 리다이렉트` + description: `'https://mysnowball.kr/auth/google/failure'로 GET요청을 보냅니다.` }) @UseGuards(AuthGuard('google')) async googleLogin(): Promise {} @Get('google/redirect') - @ApiExcludeEndpoint() @UseGuards(AuthGuard('google')) + @ApiResponse({ + status: 200, + description: 'Google 로그인 성공', + type: ResInfoDto + }) + @ApiResponse({ + status: 500, + description: 'Internal Server Error' + }) async googleLoginCallback(@Req() req, @Res() res): Promise { const profile: string = req.user.profile; - if (profile) { - res.redirect('http://localhost:3000/'); - } else res.redirect('http://localhost:3000/failure'); + const result = this.authService.createInfo(profile); + res.status(200).json(result); } @Get('naver') @@ -43,23 +48,30 @@ export class AuthController { }) @ApiResponse({ status: 200, - description: `'https://mysnowball.kr'으로 리다이렉트` + description: `'https://mysnowball.kr/auth/naver/redirect'로 GET요청을 보냅니다.` }) @ApiResponse({ status: 400, - description: `'https://mysnowball.kr/failure'으로 리다이렉트` + description: `'https://mysnowball.kr/auth/naver/failure'로 GET요청을 보냅니다.` }) @UseGuards(AuthGuard('naver')) async naverLogin(): Promise {} @Get('naver/redirect') - @ApiExcludeEndpoint() @UseGuards(AuthGuard('naver')) + @ApiResponse({ + status: 200, + description: 'Naver 로그인 성공', + type: ResInfoDto + }) + @ApiResponse({ + status: 500, + description: 'Internal Server Error' + }) async naverLoginCallBack(@Req() req, @Res() res): Promise { const profile: string = req.user.profile; - if (profile) { - res.redirect('http://localhost:3000/'); - } else res.redirect('http://localhost:3000/failure'); + const result = this.authService.createInfo(profile); + res.status(200).json(result); } @Get('kakao') @@ -69,22 +81,29 @@ export class AuthController { }) @ApiResponse({ status: 200, - description: `'https://mysnowball.kr'으로 리다이렉트` + description: `'https://mysnowball.kr/auth/kakao/redirect'로 GET요청을 보냅니다.` }) @ApiResponse({ status: 400, - description: `'https://mysnowball.kr/failure'으로 리다이렉트` + description: `'https://mysnowball.kr/auth/kakao/failure'로 GET요청을 보냅니다.` }) @UseGuards(AuthGuard('kakao')) async kakaoLogin(): Promise {} @Get('kakao/redirect') - @ApiExcludeEndpoint() @UseGuards(AuthGuard('kakao')) + @ApiResponse({ + status: 200, + description: 'Kakao 로그인 성공', + type: ResInfoDto + }) + @ApiResponse({ + status: 500, + description: 'Internal Server Error' + }) async kakaoLoginCallBack(@Req() req, @Res() res): Promise { const profile: string = req.user.profile; - if (profile) { - res.redirect('http://localhost:3000/'); - } else res.redirect('http://localhost:3000/failure'); + const result = this.authService.createInfo(profile); + res.status(200).json(result); } } diff --git a/back/src/modules/auth/auth.module.ts b/back/src/modules/auth/auth.module.ts index 393b2e0..839971e 100644 --- a/back/src/modules/auth/auth.module.ts +++ b/back/src/modules/auth/auth.module.ts @@ -4,10 +4,16 @@ import { NaverAuthStrategy } from './naver-auth.strategy'; import { KakaoAuthStrategy } from './kakao-auth.strategy'; import { AuthController } from './auth.controller'; import { PassportModule } from '@nestjs/passport'; +import { AuthService } from './auth.service'; @Module({ imports: [PassportModule], - providers: [GoogleAuthStrategy, NaverAuthStrategy, KakaoAuthStrategy], + providers: [ + GoogleAuthStrategy, + NaverAuthStrategy, + KakaoAuthStrategy, + AuthService + ], controllers: [AuthController] }) export class AuthModule {} diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts new file mode 100644 index 0000000..5cf95ce --- /dev/null +++ b/back/src/modules/auth/auth.service.ts @@ -0,0 +1,74 @@ +import { Injectable, UnauthorizedException } from '@nestjs/common'; +import { ResInfoDto } from './dto/response/res-info.dto'; +import { UserDto } from './dto/user.dto'; +import { SnowballDto } from '../snowball/dto/snowball.dto'; +@Injectable() +export class AuthService { + constructor() {} + + async createInfo(profile: any): Promise { + if (profile) { + // Example data, replace with actual data from your logic + const access_token = 'your-access-token'; + const userDto: UserDto = { + name: '김찬우', + id: 'Oauth에서 주는 값', + snowball_count: 3, + snowball_list: [ + '32413434-32a2-2342-3242-3g23-413oye3', + '32413434-32a2-2342-3242-3g23-413oye3', + '32413434-32a2-2342-3242-3g23-413oye3' + ], + message_count: 123 + }; + const mainSnowballDto: SnowballDto = { + title: '나만의 스노우볼1', + uuid: '32413434-32a2-2342-3242-3g23-413oye3', + message_private: null, + message_count_private: null, + deco_list: [ + { + decoration_id: 15, + decoration_color: '#FFFFFF', + location: 13 + }, + { + decoration_id: 12, + decoration_color: '#FFFFFF', + location: 14 + } + ], + message_list: [ + { + id: 1, + decoration_id: 15, + decoration_color: '#FFFFFF', + content: '편지 내용', + sender: '널 좋아하는 사람', + opened: null, + created: new Date('2023-12-30T17:35:31Z') + }, + { + id: 2, + decoration_id: 15, + decoration_color: '#FFFFFF', + content: '편지 내용', + sender: '찬우를 사랑하는 사람', + opened: null, + created: new Date('2023-12-30T17:35:31Z') + } + ] + }; + + const resInfoDto: ResInfoDto = { + access_token, + user: [userDto], + main_snowball: [mainSnowballDto] + }; + + return resInfoDto; + } else { + throw new UnauthorizedException('Failed to authenticate with Google'); + } + } +} diff --git a/back/src/modules/message/dto/message.dto.ts b/back/src/modules/message/dto/message.dto.ts index aff438b..5df472b 100644 --- a/back/src/modules/message/dto/message.dto.ts +++ b/back/src/modules/message/dto/message.dto.ts @@ -6,10 +6,6 @@ export class MessageDto { @ApiProperty({ type: Number, description: '메시지 ID' }) readonly id: number; - @IsString() - @ApiProperty({ type: String, description: '스노우볼 ID' }) - readonly snowball_id: string; - @IsNumber() @ApiProperty({ type: Number, description: '데코레이션 ID' }) readonly decoration_id: number; @@ -32,5 +28,5 @@ export class MessageDto { @IsDate() @ApiProperty({ type: Date, description: '생성 날짜' }) - readonly created_at: Date; + readonly created: Date; } diff --git a/back/src/modules/snowball/dto/decoration-snowball.dto.ts b/back/src/modules/snowball/dto/decoration-snowball.dto.ts index d53f1a9..f43b34c 100644 --- a/back/src/modules/snowball/dto/decoration-snowball.dto.ts +++ b/back/src/modules/snowball/dto/decoration-snowball.dto.ts @@ -5,7 +5,7 @@ export class DecorationSnowballDto { @IsNumber() @IsNotEmpty() @ApiProperty({ type: Number, description: '장식 종류' }) - readonly deco_id: number; + readonly decoration_id: number; @IsString() @IsNotEmpty() From d2097776f81ae6cd81695662fd56efe6b30f9fdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Mon, 20 Nov 2023 03:52:47 +0900 Subject: [PATCH 044/185] =?UTF-8?q?feat:=20message=20delete=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.controller.ts | 6 +++--- back/src/modules/message/message.controller.ts | 8 ++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index 3c7215f..060caab 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -28,7 +28,7 @@ export class AuthController { @UseGuards(AuthGuard('google')) @ApiResponse({ status: 200, - description: 'Google 로그인 성공', + description: 'Google 로그인 성공 및 Info 반환', type: ResInfoDto }) @ApiResponse({ @@ -61,7 +61,7 @@ export class AuthController { @UseGuards(AuthGuard('naver')) @ApiResponse({ status: 200, - description: 'Naver 로그인 성공', + description: 'Naver 로그인 성공 및 Info 반환', type: ResInfoDto }) @ApiResponse({ @@ -94,7 +94,7 @@ export class AuthController { @UseGuards(AuthGuard('kakao')) @ApiResponse({ status: 200, - description: 'Kakao 로그인 성공', + description: 'Kakao 로그인 성공 및 Info 반환', type: ResInfoDto }) @ApiResponse({ diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 1179cbd..6a66a58 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -3,6 +3,7 @@ import { MessageService } from './message.service'; import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; import { ReqDeleteMessageDto } from './dto/request/req-delete-message.dto'; import { ApiBody, ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; +import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; @ApiTags('Message API') @Controller('message') @@ -15,7 +16,11 @@ export class MessageController { description: '스노우볼에 메세지를 생성합니다.' }) @ApiBody({ type: ReqCreateMessageDto }) - @ApiResponse({ status: 201, description: 'Created' }) + @ApiResponse({ + status: 201, + description: 'Created', + type: ResCreateMessageDto + }) createMessage(@Body() createMessageDto: ReqCreateMessageDto) { return this.messageService.createMessage(createMessageDto); } @@ -25,7 +30,6 @@ export class MessageController { summary: '메세지 삭제 API', description: '스노우볼에서 특정 메세지를 삭제합니다.' }) - @ApiBody({ type: ReqDeleteMessageDto }) @ApiResponse({ status: 204, description: 'No Content' }) deleteMessage(@Param() deleteMessageDto: ReqDeleteMessageDto) { this.messageService.deleteMessage(deleteMessageDto); From 66061c4366fe896f7bc7ce8b4cf332abbe9542b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Mon, 20 Nov 2023 04:56:45 +0900 Subject: [PATCH 045/185] =?UTF-8?q?feat:=20message=20&=20auth=20swagger=20?= =?UTF-8?q?=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.controller.ts | 17 +++++----- back/src/modules/auth/auth.service.ts | 1 + .../dto/request/req-create-message.dto.ts | 7 ++--- .../modules/message/entity/message.entity.ts | 2 +- .../src/modules/message/message.controller.ts | 31 ++++++++++++++++--- back/src/modules/message/message.service.ts | 20 +++++++++--- .../dto/request/req-update-decoration.dto.ts | 9 +++--- .../dto/request/req-update-snowball.dto.ts | 9 +++--- back/src/modules/snowball/dto/snowball.dto.ts | 6 ++++ back/src/modules/snowball/snowball.service.ts | 2 +- test | 1 - 11 files changed, 73 insertions(+), 32 deletions(-) delete mode 160000 test diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index 060caab..59cc64b 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Get, Req, Res, UseGuards } from '@nestjs/common'; +import { Controller, Get, Req, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; import { ResInfoDto } from './dto/response/res-info.dto'; @@ -31,14 +31,15 @@ export class AuthController { description: 'Google 로그인 성공 및 Info 반환', type: ResInfoDto }) + @ApiResponse({ status: 401, description: 'Unauthorized' }) @ApiResponse({ status: 500, description: 'Internal Server Error' }) - async googleLoginCallback(@Req() req, @Res() res): Promise { + async googleLoginCallback(@Req() req): Promise { const profile: string = req.user.profile; const result = this.authService.createInfo(profile); - res.status(200).json(result); + return result; } @Get('naver') @@ -64,14 +65,15 @@ export class AuthController { description: 'Naver 로그인 성공 및 Info 반환', type: ResInfoDto }) + @ApiResponse({ status: 401, description: 'Unauthorized' }) @ApiResponse({ status: 500, description: 'Internal Server Error' }) - async naverLoginCallBack(@Req() req, @Res() res): Promise { + async naverLoginCallBack(@Req() req): Promise { const profile: string = req.user.profile; const result = this.authService.createInfo(profile); - res.status(200).json(result); + return result; } @Get('kakao') @@ -97,13 +99,14 @@ export class AuthController { description: 'Kakao 로그인 성공 및 Info 반환', type: ResInfoDto }) + @ApiResponse({ status: 401, description: 'Unauthorized' }) @ApiResponse({ status: 500, description: 'Internal Server Error' }) - async kakaoLoginCallBack(@Req() req, @Res() res): Promise { + async kakaoLoginCallBack(@Req() req): Promise { const profile: string = req.user.profile; const result = this.authService.createInfo(profile); - res.status(200).json(result); + return result; } } diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index 5cf95ce..9b9663b 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -23,6 +23,7 @@ export class AuthService { }; const mainSnowballDto: SnowballDto = { title: '나만의 스노우볼1', + id: 1, uuid: '32413434-32a2-2342-3242-3g23-413oye3', message_private: null, message_count_private: null, diff --git a/back/src/modules/message/dto/request/req-create-message.dto.ts b/back/src/modules/message/dto/request/req-create-message.dto.ts index 1b995b5..94f3427 100644 --- a/back/src/modules/message/dto/request/req-create-message.dto.ts +++ b/back/src/modules/message/dto/request/req-create-message.dto.ts @@ -1,12 +1,11 @@ import { IsString, IsNotEmpty, IsNumber } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -import { IsUUID } from 'class-validator'; export class ReqCreateMessageDto { @IsNotEmpty() - @IsUUID('4') - @ApiProperty({ type: String, description: '스노우볼 uuid' }) - readonly snowball_id: string; + @IsNumber() + @ApiProperty({ type: Number, description: '스노우볼 id' }) + readonly snowball_id: number; @IsString() @IsNotEmpty() diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 29957ee..e54f137 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -14,7 +14,7 @@ export class MessageEntity { id: number; @Column() - snowball_id: string; + snowball_id: number; @Column() decoration_id: number; diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 6a66a58..59d0236 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -1,4 +1,11 @@ -import { Controller, Post, Delete, Body, Param } from '@nestjs/common'; +import { + Controller, + Post, + Delete, + Body, + Param, + HttpCode +} from '@nestjs/common'; import { MessageService } from './message.service'; import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; import { ReqDeleteMessageDto } from './dto/request/req-delete-message.dto'; @@ -11,6 +18,7 @@ export class MessageController { constructor(private readonly messageService: MessageService) {} @Post() + @HttpCode(201) @ApiOperation({ summary: '메세지 생성 API', description: '스노우볼에 메세지를 생성합니다.' @@ -21,17 +29,30 @@ export class MessageController { description: 'Created', type: ResCreateMessageDto }) - createMessage(@Body() createMessageDto: ReqCreateMessageDto) { - return this.messageService.createMessage(createMessageDto); + @ApiResponse({ + status: 500, + description: 'Insert Fail' + }) + async createMessage( + @Body() createMessageDto: ReqCreateMessageDto + ): Promise { + const resCreateMessage = + await this.messageService.createMessage(createMessageDto); + return resCreateMessage; } @Delete(':message_id') + @HttpCode(204) @ApiOperation({ summary: '메세지 삭제 API', description: '스노우볼에서 특정 메세지를 삭제합니다.' }) @ApiResponse({ status: 204, description: 'No Content' }) - deleteMessage(@Param() deleteMessageDto: ReqDeleteMessageDto) { - this.messageService.deleteMessage(deleteMessageDto); + @ApiResponse({ + status: 500, + description: 'Delete Fail' + }) + async deleteMessage(@Param() deleteMessageDto: ReqDeleteMessageDto) { + await this.messageService.deleteMessage(deleteMessageDto); } } diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index a95efee..8b197fd 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -4,6 +4,7 @@ import { Repository } from 'typeorm'; import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; import { ReqDeleteMessageDto } from './dto/request/req-delete-message.dto'; import { MessageEntity } from './entity/message.entity'; +import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; @Injectable() export class MessageService { @@ -13,15 +14,24 @@ export class MessageService { ) {} async createMessage( createMessageDto: ReqCreateMessageDto - ): Promise { + ): Promise { const messageEntity = this.messageRepository.create({ snowball_id: createMessageDto.snowball_id, - decoration_id: createMessageDto.decoration_id, + sender: createMessageDto.sender, content: createMessageDto.content, - sender: createMessageDto.sender - // opened와 created_at은 자동으로 설정됩니다. + decoration_id: createMessageDto.decoration_id, + decoration_color: createMessageDto.decoration_color + // opened와 created_at은 자동으로 설정 }); - return await this.messageRepository.save(messageEntity); + const savedMessage = await this.messageRepository.save(messageEntity); + + // 이 부분에서 필터링 로직을 작성 + const resCreateMessage: ResCreateMessageDto = { + sender: savedMessage.sender, + content: savedMessage.content + }; + + return resCreateMessage; } async deleteMessage(deleteMessageDto: ReqDeleteMessageDto): Promise { await this.messageRepository.delete(deleteMessageDto.message_id); diff --git a/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts b/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts index 88f18a3..6724841 100644 --- a/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts +++ b/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts @@ -1,12 +1,13 @@ -import { IsUUID, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; +import { IsNumber, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; import { DecorationSnowballDto } from '../decoration-snowball.dto'; export class ReqUpdateSnowballDecoDto { - @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) - @IsUUID('4') - snowball_uuid: string; + @IsNotEmpty() + @IsNumber() + @ApiProperty({ type: Number, description: '스노우볼 id' }) + readonly snowball_id: number; @IsNotEmpty() @ValidateNested({ each: true }) diff --git a/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts b/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts index f790222..1a809fc 100644 --- a/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts @@ -1,15 +1,16 @@ import { IsString, - IsUUID, + IsNumber, IsNotEmpty, IsBoolean } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class ReqUpdateSnowballDto { - @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) - @IsUUID('4') - snowball_uuid: string; + @IsNotEmpty() + @IsNumber() + @ApiProperty({ type: Number, description: '스노우볼 id' }) + readonly snowball_id: number; @IsString() @IsNotEmpty() diff --git a/back/src/modules/snowball/dto/snowball.dto.ts b/back/src/modules/snowball/dto/snowball.dto.ts index d66802f..44cbec9 100644 --- a/back/src/modules/snowball/dto/snowball.dto.ts +++ b/back/src/modules/snowball/dto/snowball.dto.ts @@ -2,6 +2,7 @@ import { IsString, IsUUID, IsBoolean, + IsNumber, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; @@ -16,6 +17,11 @@ export class SnowballDto { @ApiProperty({ type: String, description: '스노우볼 제목' }) readonly title: string; + @IsNotEmpty() + @IsNumber() + @ApiProperty({ type: Number, description: '스노우볼 id' }) + readonly id: number; + @IsUUID('4') @IsNotEmpty() @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 79e4f98..91b0b4c 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -18,6 +18,6 @@ export class SnowballService { return await this.snowballRepository.save(snowball); } async updateSnowball(updateSnowballDto: ReqUpdateSnowballDto): Promise { - await this.snowballRepository.delete(updateSnowballDto.snowball_uuid); + await this.snowballRepository.delete(updateSnowballDto.snowball_id); } } diff --git a/test b/test deleted file mode 160000 index 38a4089..0000000 --- a/test +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 38a4089437755bfca532f4eba4a83ae5a5c443d9 From 67fed55b575d2c1842bd636fb18e83103f15ecf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Mon, 20 Nov 2023 01:34:04 +0900 Subject: [PATCH 046/185] committing changes before rebase --- .github/workflows/FrontEnd.yml | 50 ++++++++++++++++++++++++++++++++++ .gitignore | 6 ++++ back/.gitignore | 37 ------------------------- package.json | 5 ++++ 4 files changed, 61 insertions(+), 37 deletions(-) create mode 100644 .github/workflows/FrontEnd.yml create mode 100644 .gitignore delete mode 100644 back/.gitignore create mode 100644 package.json diff --git a/.github/workflows/FrontEnd.yml b/.github/workflows/FrontEnd.yml new file mode 100644 index 0000000..012a66e --- /dev/null +++ b/.github/workflows/FrontEnd.yml @@ -0,0 +1,50 @@ +# This is a basic workflow to help you get started with Actions + +name: FrontEnd deploy + +# Controls when the workflow will run +on: + push: + branches: [ "FE/main" ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + build: + runs-on: ubuntu-latest + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v3 + + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '18' + + - name: Check Node v + run: node -v + + - name: Install dependencies + working-directory: ./front + run: npm install + + - name: Generate build + working-directory: ./front + run: npm run build + + - name: Deploy + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + run: | + aws s3 sync ./front/dist s3://snowball-ssock --region ap-northeast-2 --delete + + # 업로드한 s3 파일을 각 CDN 캐시 무효화하여 리프레시 하기 + - name: CloudFront Invalidation + env: + CLOUD_FRONT_ID: ${{ secrets.AWS_CLOUDFRONT_ID}} + run: | + aws cloudfront create-invalidation \ + --distribution-id $CLOUD_FRONT_ID --paths '/*' diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5599baf --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# compiled output +back/dist +/node_modules +back/node_modules +back/.env +back/test \ No newline at end of file diff --git a/back/.gitignore b/back/.gitignore deleted file mode 100644 index ea48d65..0000000 --- a/back/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -# compiled output -/dist -/node_modules - -# Logs -logs -*.log -npm-debug.log* -pnpm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# OS -.DS_Store - -# Tests -/coverage -/.nyc_output - -# IDEs and editors -/.idea -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace - -# IDE - VSCode -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json - -.env \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..7ed19b9 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@nestjs/class-validator": "^0.13.4" + } +} From c68098da64ee8d4c560b524f0008b73ed9c33c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Mon, 20 Nov 2023 01:44:46 +0900 Subject: [PATCH 047/185] =?UTF-8?q?fix:=20api=20=EB=AA=85=EC=84=B8?= =?UTF-8?q?=EC=99=80=20=EB=8B=A4=EB=A5=B8=20=EB=B6=80=EB=B6=84=EB=93=A4=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/config/ormconfig.ts | 3 ++- .../modules/message/entity/message.entity.ts | 6 ++--- .../snowball/dto/req-create-snowball.dto.ts | 4 +-- .../snowball/dto/req-update-snowball.dto.ts | 13 +++++----- .../snowball/dto/res-create-snowball.dto.ts | 26 +++---------------- .../snowball/dto/res-update-snowball.dto.ts | 2 +- .../entity/snowball-decoration.entity.ts | 4 +-- .../snowball/entity/snowball.entity.ts | 2 +- .../modules/snowball/entity/user.entity.ts | 3 +-- back/src/modules/snowball/snowball.service.ts | 2 +- 10 files changed, 23 insertions(+), 42 deletions(-) diff --git a/back/src/config/ormconfig.ts b/back/src/config/ormconfig.ts index a61ec16..11e9680 100644 --- a/back/src/config/ormconfig.ts +++ b/back/src/config/ormconfig.ts @@ -10,6 +10,7 @@ const typeOrmConfig: TypeOrmModuleOptions = { password: process.env.DATABASE_PASSWORD, database: process.env.DATABASE_SCHEMA, entities: [process.env.ENTITY_PATH], - synchronize: true + synchronize: true, + logging: true }; export default typeOrmConfig; diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 389e7a4..29957ee 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -8,7 +8,7 @@ import { } from 'typeorm'; import { SnowballEntity } from 'src/modules/snowball/entity/snowball.entity'; -@Entity({ synchronize: true ,name: 'message' }) +@Entity({ synchronize: true, name: 'message' }) export class MessageEntity { @PrimaryGeneratedColumn() id: number; @@ -19,13 +19,13 @@ export class MessageEntity { @Column() decoration_id: number; - @Column({ length: 7}) + @Column({ length: 7 }) decoration_color: string; @Column({ type: 'text' }) content: string; - @Column({ length: 16}) + @Column({ length: 16 }) sender: string; @CreateDateColumn({ nullable: true, default: null }) diff --git a/back/src/modules/snowball/dto/req-create-snowball.dto.ts b/back/src/modules/snowball/dto/req-create-snowball.dto.ts index a8b6c45..34e401c 100644 --- a/back/src/modules/snowball/dto/req-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/req-create-snowball.dto.ts @@ -31,7 +31,7 @@ export class CreateSnowballDto { @IsNotEmpty() @ApiProperty({ type: Boolean, - description: '스노우볼 속 메시지들 비공개 여부를 가리키는 불리언' + description: '스노우볼 속 메시지들 비공개 여부' }) readonly message_private: boolean; @@ -39,7 +39,7 @@ export class CreateSnowballDto { @IsNotEmpty() @ApiProperty({ type: Boolean, - description: '스노우볼 속 메시지 갯수의 비공개 여부를 가리키는 불리언' + description: '스노우볼 속 메시지 갯수의 비공개 여부' }) readonly message_count_private: boolean; } diff --git a/back/src/modules/snowball/dto/req-update-snowball.dto.ts b/back/src/modules/snowball/dto/req-update-snowball.dto.ts index 7831f09..0131269 100644 --- a/back/src/modules/snowball/dto/req-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/req-update-snowball.dto.ts @@ -1,16 +1,15 @@ import { IsString, - IsNumber, + IsUUID, IsNotEmpty, IsBoolean } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class UpdateSnowballDto { - @IsNumber() - @IsNotEmpty() - @ApiProperty({ type: Number, description: '유저의 id' }) - readonly user_id: number; + @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) + @IsUUID('4') + snowball_uuid: string; @IsString() @IsNotEmpty() @@ -21,7 +20,7 @@ export class UpdateSnowballDto { @IsNotEmpty() @ApiProperty({ type: Boolean, - description: '스노우볼 속 메시지들 비공개 여부를 가리키는 불리언' + description: '스노우볼 속 메시지들 비공개 여부' }) readonly message_private: boolean; @@ -29,7 +28,7 @@ export class UpdateSnowballDto { @IsNotEmpty() @ApiProperty({ type: Boolean, - description: '스노우볼 속 메시지 갯수의 비공개 여부를 가리키는 불리언' + description: '스노우볼 속 메시지 갯수 비공개 여부' }) readonly message_count_private: boolean; } diff --git a/back/src/modules/snowball/dto/res-create-snowball.dto.ts b/back/src/modules/snowball/dto/res-create-snowball.dto.ts index 566ad20..52a1886 100644 --- a/back/src/modules/snowball/dto/res-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/res-create-snowball.dto.ts @@ -1,33 +1,15 @@ -import { IsBoolean, ValidateNested } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; import { IsString, IsDate, IsUUID } from 'class-validator'; -import { DecorationSnowballDto } from './decoration-snowball.dto'; - export class ResCreateSnowballDto { @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) - @IsUUID() + @IsUUID('4') snowball_uuid: string; - @ApiProperty({ description: '생성된 스노우볼의 제목' }) + @ApiProperty({ description: '필터링된 스노우볼의 제목' }) @IsString() title: string; - @ValidateNested({ each: true }) - @ApiProperty({ - type: [DecorationSnowballDto], - description: '데코오브젝트들이 들어있는 리스트' - }) - readonly deco_list: DecorationSnowballDto[]; - - @ApiProperty({ description: '메시지들의 공개 여부 (True이면 비공개)' }) - @IsBoolean() - message_private: boolean; - - @ApiProperty({ description: '받은 메시지 수 공개 여부 (True이면 비공개)' }) - @IsBoolean() - message_count_private: boolean; - - @ApiProperty({ description: '스노우볼이 언제 생성되었는지' }) + @ApiProperty({ description: '스노우볼 생성 시간' }) @IsDate() - createdAt: Date; + created_at: Date; } diff --git a/back/src/modules/snowball/dto/res-update-snowball.dto.ts b/back/src/modules/snowball/dto/res-update-snowball.dto.ts index a2d6324..cc9b6ac 100644 --- a/back/src/modules/snowball/dto/res-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/res-update-snowball.dto.ts @@ -11,7 +11,7 @@ export class ResUpdateSnowballDto { readonly snowball_id: number; @IsString() - @ApiProperty({ type: String, description: '스노우볼 제목' }) + @ApiProperty({ type: String, description: '변경된 스노우볼 제목' }) readonly title: string; @IsBoolean() diff --git a/back/src/modules/snowball/entity/snowball-decoration.entity.ts b/back/src/modules/snowball/entity/snowball-decoration.entity.ts index c9d6429..d779663 100644 --- a/back/src/modules/snowball/entity/snowball-decoration.entity.ts +++ b/back/src/modules/snowball/entity/snowball-decoration.entity.ts @@ -7,7 +7,7 @@ import { } from 'typeorm'; import { SnowballEntity } from './snowball.entity'; -@Entity({ synchronize: true ,name: 'snowball_decoration' }) +@Entity({ name: 'snowball_decoration' }) export class SnowballDecorationEntity { @PrimaryGeneratedColumn() id: number; @@ -18,7 +18,7 @@ export class SnowballDecorationEntity { @Column() decoration_id: number; - @Column({ length: 7}) + @Column({ length: 7 }) decoration_color: string; @Column() diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index a207142..f72e71a 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -13,7 +13,7 @@ import { UserEntity } from './user.entity'; import { SnowballDecorationEntity } from './snowball-decoration.entity'; import { MessageEntity } from '../../message/entity/message.entity'; -@Entity({ synchronize: true ,name: 'snowball' }) +@Entity({ name: 'snowball' }) export class SnowballEntity { @PrimaryGeneratedColumn() id: number; diff --git a/back/src/modules/snowball/entity/user.entity.ts b/back/src/modules/snowball/entity/user.entity.ts index 29a5f48..b397bd7 100644 --- a/back/src/modules/snowball/entity/user.entity.ts +++ b/back/src/modules/snowball/entity/user.entity.ts @@ -7,8 +7,7 @@ import { } from 'typeorm'; import { SnowballEntity } from './snowball.entity'; - -@Entity({synchronize: true , name: 'user' }) +@Entity({ name: 'user' }) export class UserEntity { @PrimaryGeneratedColumn() id: number; diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 301dd3f..b304d07 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -18,6 +18,6 @@ export class SnowballService { return await this.snowballRepository.save(snowball); } async updateSnowball(updateSnowballDto: UpdateSnowballDto): Promise { - await this.snowballRepository.delete(updateSnowballDto.user_id); + await this.snowballRepository.delete(updateSnowballDto.snowball_uuid); } } From ffc0f70666f9aee2ba203c64057e5dae182d9e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Mon, 20 Nov 2023 02:12:48 +0900 Subject: [PATCH 048/185] =?UTF-8?q?feat:=20message=20&=20update=20deco=20D?= =?UTF-8?q?TO=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/modules/auth/dto/main-snowball.dto.ts | 60 +++++++++++++++++++ back/src/modules/auth/dto/message.dto.ts | 36 +++++++++++ back/src/modules/auth/dto/res-info.dto.ts | 41 +++++++++++++ back/src/modules/auth/dto/user.dto.ts | 37 ++++++++++++ ...ssage.dto.ts => req-create-message.dto.ts} | 3 +- ...ssage.dto.ts => req-delete-message.dto.ts} | 0 .../message/dto/res-create-message.dto.ts | 17 ++++++ .../src/modules/message/message.controller.ts | 4 +- back/src/modules/message/message.service.ts | 4 +- .../snowball/dto/req-create-snowball.dto.ts | 8 ++- .../snowball/dto/req-update-decoration.dto.ts | 25 ++++++++ .../snowball/dto/res-create-snowball.dto.ts | 2 +- .../snowball/dto/res-update-decoration.dto.ts | 25 ++++++++ .../snowball/dto/res-update-snowball.dto.ts | 4 +- 14 files changed, 256 insertions(+), 10 deletions(-) create mode 100644 back/src/modules/auth/dto/main-snowball.dto.ts create mode 100644 back/src/modules/auth/dto/message.dto.ts create mode 100644 back/src/modules/auth/dto/res-info.dto.ts create mode 100644 back/src/modules/auth/dto/user.dto.ts rename back/src/modules/message/dto/{create-message.dto.ts => req-create-message.dto.ts} (93%) rename back/src/modules/message/dto/{delete-message.dto.ts => req-delete-message.dto.ts} (100%) create mode 100644 back/src/modules/message/dto/res-create-message.dto.ts create mode 100644 back/src/modules/snowball/dto/req-update-decoration.dto.ts create mode 100644 back/src/modules/snowball/dto/res-update-decoration.dto.ts diff --git a/back/src/modules/auth/dto/main-snowball.dto.ts b/back/src/modules/auth/dto/main-snowball.dto.ts new file mode 100644 index 0000000..e42745e --- /dev/null +++ b/back/src/modules/auth/dto/main-snowball.dto.ts @@ -0,0 +1,60 @@ +import { + IsString, + IsUUID, + IsBoolean, + IsNotEmpty, + IsArray, + ValidateNested +} from '@nestjs/class-validator'; +import { Type } from '@nestjs/class-transformer'; +import { ApiProperty } from '@nestjs/swagger'; +import { DecorationSnowballDto } from '../../snowball/dto/decoration-snowball.dto'; +import { MessageDto } from './message.dto'; + +export class MainSnowballDto { + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '스노우볼 제목' }) + readonly title: string; + + @IsUUID('4') + @IsNotEmpty() + @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) + readonly uuid: string; + + @IsBoolean() + @IsNotEmpty() + @ApiProperty({ + type: Boolean, + description: '스노우볼 속 메시지들 비공개 여부' + }) + readonly message_private: boolean; + + @IsBoolean() + @IsNotEmpty() + @ApiProperty({ + type: Boolean, + description: '스노우볼 속 메시지 갯수 비공개 여부' + }) + readonly message_count_private: boolean; + + @IsNotEmpty() + @IsArray() + @ValidateNested({ each: true }) + @Type(() => DecorationSnowballDto) + @ApiProperty({ + type: [DecorationSnowballDto], + description: '데코오브젝트들이 들어있는 리스트' + }) + readonly deco_list: DecorationSnowballDto[]; + + @IsNotEmpty() + @IsArray() + @ValidateNested({ each: true }) + @Type(() => MessageDto) + @ApiProperty({ + type: [MessageDto], + description: '스노우볼 속 메시지 리스트' + }) + readonly message_list: MessageDto[]; +} diff --git a/back/src/modules/auth/dto/message.dto.ts b/back/src/modules/auth/dto/message.dto.ts new file mode 100644 index 0000000..aff438b --- /dev/null +++ b/back/src/modules/auth/dto/message.dto.ts @@ -0,0 +1,36 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsString, IsNumber, IsDate } from 'class-validator'; + +export class MessageDto { + @IsNumber() + @ApiProperty({ type: Number, description: '메시지 ID' }) + readonly id: number; + + @IsString() + @ApiProperty({ type: String, description: '스노우볼 ID' }) + readonly snowball_id: string; + + @IsNumber() + @ApiProperty({ type: Number, description: '데코레이션 ID' }) + readonly decoration_id: number; + + @IsString() + @ApiProperty({ type: String, description: '데코레이션 색상' }) + readonly decoration_color: string; + + @IsString() + @ApiProperty({ type: String, description: '메시지 내용' }) + readonly content: string; + + @IsString() + @ApiProperty({ type: String, description: '보낸이' }) + readonly sender: string; + + @IsDate() + @ApiProperty({ type: Date, description: '열린 날짜' }) + readonly opened: Date | null; + + @IsDate() + @ApiProperty({ type: Date, description: '생성 날짜' }) + readonly created_at: Date; +} diff --git a/back/src/modules/auth/dto/res-info.dto.ts b/back/src/modules/auth/dto/res-info.dto.ts new file mode 100644 index 0000000..5569c18 --- /dev/null +++ b/back/src/modules/auth/dto/res-info.dto.ts @@ -0,0 +1,41 @@ +import { + IsString, + IsNotEmpty, + ValidateNested, + IsArray +} from '@nestjs/class-validator'; +import { ApiProperty } from '@nestjs/swagger'; +import { UserDto } from './user.dto'; +import { MainSnowballDto } from './main-snowball.dto'; +import { Type } from '@nestjs/class-transformer'; + +export class InfoDto { + @IsNotEmpty() + @IsString() + @ApiProperty({ + type: String, + description: 'Bearer 타입의 OAuth 2.0 액세스 토큰', + example: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' + }) + readonly access_token: string; + + @IsNotEmpty() + @IsArray() + @ValidateNested({ each: true }) + @Type(() => UserDto) + @ApiProperty({ + type: UserDto, + description: '사용자 정보 배열' + }) + readonly user: UserDto[]; + + @IsNotEmpty() + @IsArray() + @ValidateNested({ each: true }) + @Type(() => MainSnowballDto) + @ApiProperty({ + type: MainSnowballDto, + description: '메인 스노우볼 정보 배열' + }) + readonly main_snowball: MainSnowballDto[]; +} diff --git a/back/src/modules/auth/dto/user.dto.ts b/back/src/modules/auth/dto/user.dto.ts new file mode 100644 index 0000000..67d0b1c --- /dev/null +++ b/back/src/modules/auth/dto/user.dto.ts @@ -0,0 +1,37 @@ +import { + IsString, + IsNumber, + IsUUID, + IsNotEmpty +} from '@nestjs/class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class UserDto { + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '사용자 이름' }) + readonly name: string; + + @IsUUID('4') + @IsNotEmpty() + @ApiProperty({ format: 'uuid', description: 'Oauth에서 주는 값' }) + readonly id: string; + + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '스노우볼 갯수' }) + readonly snowball_count: number; + + @IsNotEmpty() + @ApiProperty({ + type: [String], + format: 'uuid', + description: '스노우볼 UUID 리스트' + }) + readonly snowball_list: string[]; + + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '메시지 갯수' }) + readonly message_count: number; +} diff --git a/back/src/modules/message/dto/create-message.dto.ts b/back/src/modules/message/dto/req-create-message.dto.ts similarity index 93% rename from back/src/modules/message/dto/create-message.dto.ts rename to back/src/modules/message/dto/req-create-message.dto.ts index 45d1270..b6520ae 100644 --- a/back/src/modules/message/dto/create-message.dto.ts +++ b/back/src/modules/message/dto/req-create-message.dto.ts @@ -1,9 +1,10 @@ import { IsString, IsNotEmpty, IsNumber } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; +import { IsUUID } from 'class-validator'; export class CreateMessageDto { @IsNotEmpty() - @IsString() + @IsUUID('4') @ApiProperty({ type: String, description: '스노우볼 uuid' }) readonly snowball_id: string; diff --git a/back/src/modules/message/dto/delete-message.dto.ts b/back/src/modules/message/dto/req-delete-message.dto.ts similarity index 100% rename from back/src/modules/message/dto/delete-message.dto.ts rename to back/src/modules/message/dto/req-delete-message.dto.ts diff --git a/back/src/modules/message/dto/res-create-message.dto.ts b/back/src/modules/message/dto/res-create-message.dto.ts new file mode 100644 index 0000000..18ee020 --- /dev/null +++ b/back/src/modules/message/dto/res-create-message.dto.ts @@ -0,0 +1,17 @@ +import { IsString, IsNotEmpty } from '@nestjs/class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class CreateMessageDto { + @IsString() + @IsNotEmpty() + @ApiProperty({ + type: String, + description: '필터링된 익명 사용자 닉네임(From)' + }) + readonly sender: string; + + @IsString() + @IsNotEmpty() + @ApiProperty({ type: String, description: '필터링된 메세지 내용' }) + readonly content: string; +} diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index ae491b5..b728e2d 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -1,7 +1,7 @@ import { Controller, Post, Delete, Body, Param } from '@nestjs/common'; import { MessageService } from './message.service'; -import { CreateMessageDto } from './dto/create-message.dto'; -import { DeleteMessageDto } from './dto/delete-message.dto'; +import { CreateMessageDto } from './dto/req-create-message.dto'; +import { DeleteMessageDto } from './dto/req-delete-message.dto'; import { ApiBody, ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; @ApiTags('Message API') diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 35c6138..a62b7dc 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { CreateMessageDto } from './dto/create-message.dto'; -import { DeleteMessageDto } from './dto/delete-message.dto'; +import { CreateMessageDto } from './dto/req-create-message.dto'; +import { DeleteMessageDto } from './dto/req-delete-message.dto'; import { MessageEntity } from './entity/message.entity'; @Injectable() diff --git a/back/src/modules/snowball/dto/req-create-snowball.dto.ts b/back/src/modules/snowball/dto/req-create-snowball.dto.ts index 34e401c..31b480c 100644 --- a/back/src/modules/snowball/dto/req-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/req-create-snowball.dto.ts @@ -3,17 +3,21 @@ import { IsNumber, IsNotEmpty, IsBoolean, + IsArray, ValidateNested } from '@nestjs/class-validator'; +import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; import { DecorationSnowballDto } from './decoration-snowball.dto'; export class CreateSnowballDto { @IsNotEmpty() + @IsArray() @ValidateNested({ each: true }) + @Type(() => DecorationSnowballDto) @ApiProperty({ type: [DecorationSnowballDto], - description: '데코오브젝트들이 들어있는 리스트' + description: '데코오브젝트들이 들어있는 배열' }) readonly deco_list: DecorationSnowballDto[]; @@ -39,7 +43,7 @@ export class CreateSnowballDto { @IsNotEmpty() @ApiProperty({ type: Boolean, - description: '스노우볼 속 메시지 갯수의 비공개 여부' + description: '스노우볼 속 메시지 갯수 비공개 여부' }) readonly message_count_private: boolean; } diff --git a/back/src/modules/snowball/dto/req-update-decoration.dto.ts b/back/src/modules/snowball/dto/req-update-decoration.dto.ts new file mode 100644 index 0000000..97ea2ed --- /dev/null +++ b/back/src/modules/snowball/dto/req-update-decoration.dto.ts @@ -0,0 +1,25 @@ +import { + IsUUID, + IsNotEmpty, + ValidateNested, + IsArray +} from '@nestjs/class-validator'; +import { Type } from '@nestjs/class-transformer'; +import { ApiProperty } from '@nestjs/swagger'; +import { DecorationSnowballDto } from './decoration-snowball.dto'; + +export class UpdateSnowballDto { + @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) + @IsUUID('4') + snowball_uuid: string; + + @IsNotEmpty() + @IsArray() + @ValidateNested({ each: true }) + @Type(() => DecorationSnowballDto) + @ApiProperty({ + type: [DecorationSnowballDto], + description: '데코오브젝트들이 들어있는 배열' + }) + readonly deco_list: DecorationSnowballDto[]; +} diff --git a/back/src/modules/snowball/dto/res-create-snowball.dto.ts b/back/src/modules/snowball/dto/res-create-snowball.dto.ts index 52a1886..8b8945b 100644 --- a/back/src/modules/snowball/dto/res-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/res-create-snowball.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsString, IsDate, IsUUID } from 'class-validator'; export class ResCreateSnowballDto { - @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) + @ApiProperty({ format: 'uuid', description: '변경된 스노우볼 UUID' }) @IsUUID('4') snowball_uuid: string; diff --git a/back/src/modules/snowball/dto/res-update-decoration.dto.ts b/back/src/modules/snowball/dto/res-update-decoration.dto.ts new file mode 100644 index 0000000..1dbb90b --- /dev/null +++ b/back/src/modules/snowball/dto/res-update-decoration.dto.ts @@ -0,0 +1,25 @@ +import { + IsUUID, + IsNotEmpty, + ValidateNested, + IsArray +} from '@nestjs/class-validator'; +import { Type } from '@nestjs/class-transformer'; +import { ApiProperty } from '@nestjs/swagger'; +import { DecorationSnowballDto } from './decoration-snowball.dto'; + +export class UpdateSnowballDto { + @ApiProperty({ format: 'uuid', description: '변경된 스노우볼 UUID' }) + @IsUUID('4') + snowball_uuid: string; + + @IsNotEmpty() + @IsArray() + @ValidateNested({ each: true }) + @Type(() => DecorationSnowballDto) + @ApiProperty({ + type: [DecorationSnowballDto], + description: '변경된 데코오브젝트들이 들어있는 배열' + }) + readonly deco_list: DecorationSnowballDto[]; +} diff --git a/back/src/modules/snowball/dto/res-update-snowball.dto.ts b/back/src/modules/snowball/dto/res-update-snowball.dto.ts index cc9b6ac..25d8e63 100644 --- a/back/src/modules/snowball/dto/res-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/res-update-snowball.dto.ts @@ -17,14 +17,14 @@ export class ResUpdateSnowballDto { @IsBoolean() @ApiProperty({ type: Boolean, - description: '메시지들의 공개 여부 (True이면 비공개)' + description: '변경된 스노우볼 속 메시지들 비공개 여부' }) readonly message_private: boolean; @IsBoolean() @ApiProperty({ type: Boolean, - description: '받은 메시지 수 공개 여부 (True이면 비공개)' + description: '변경된 스노우볼 속 메시지 갯수 비공개 여부' }) readonly message_count_private: boolean; } From 95caf6b15dfd7a7dada6191522e809b5e9f6b5e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Mon, 20 Nov 2023 02:27:35 +0900 Subject: [PATCH 049/185] =?UTF-8?q?feat:=20dto=20=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20=EC=9E=90?= =?UTF-8?q?=EC=9E=98=ED=95=9C=20=EB=B3=80=EA=B2=BD=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/dto/{ => response}/res-info.dto.ts | 21 +++++++------------ .../{auth => message}/dto/message.dto.ts | 0 .../{ => request}/req-create-message.dto.ts | 2 +- .../{ => request}/req-delete-message.dto.ts | 2 +- .../{ => response}/res-create-message.dto.ts | 2 +- .../src/modules/message/message.controller.ts | 4 ++-- back/src/modules/message/message.service.ts | 4 ++-- .../{ => request}/req-create-snowball.dto.ts | 6 ++---- .../req-update-decoration.dto.ts | 10 ++------- .../{ => request}/req-update-snowball.dto.ts | 2 +- .../{ => response}/res-create-snowball.dto.ts | 0 .../res-update-decoration.dto.ts | 10 ++------- .../{ => response}/res-update-snowball.dto.ts | 0 .../dto/snowball.dto.ts} | 7 ++----- .../modules/snowball/snowball.controller.ts | 16 +++++++------- back/src/modules/snowball/snowball.service.ts | 8 +++---- 16 files changed, 35 insertions(+), 59 deletions(-) rename back/src/modules/auth/dto/{ => response}/res-info.dto.ts (65%) rename back/src/modules/{auth => message}/dto/message.dto.ts (100%) rename back/src/modules/message/dto/{ => request}/req-create-message.dto.ts (96%) rename back/src/modules/message/dto/{ => request}/req-delete-message.dto.ts (87%) rename back/src/modules/message/dto/{ => response}/res-create-message.dto.ts (92%) rename back/src/modules/snowball/dto/{ => request}/req-create-snowball.dto.ts (89%) rename back/src/modules/snowball/dto/{ => request}/req-update-decoration.dto.ts (79%) rename back/src/modules/snowball/dto/{ => request}/req-update-snowball.dto.ts (95%) rename back/src/modules/snowball/dto/{ => response}/res-create-snowball.dto.ts (100%) rename back/src/modules/snowball/dto/{ => response}/res-update-decoration.dto.ts (79%) rename back/src/modules/snowball/dto/{ => response}/res-update-snowball.dto.ts (100%) rename back/src/modules/{auth/dto/main-snowball.dto.ts => snowball/dto/snowball.dto.ts} (92%) diff --git a/back/src/modules/auth/dto/res-info.dto.ts b/back/src/modules/auth/dto/response/res-info.dto.ts similarity index 65% rename from back/src/modules/auth/dto/res-info.dto.ts rename to back/src/modules/auth/dto/response/res-info.dto.ts index 5569c18..44bb941 100644 --- a/back/src/modules/auth/dto/res-info.dto.ts +++ b/back/src/modules/auth/dto/response/res-info.dto.ts @@ -1,15 +1,10 @@ -import { - IsString, - IsNotEmpty, - ValidateNested, - IsArray -} from '@nestjs/class-validator'; +import { IsString, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -import { UserDto } from './user.dto'; -import { MainSnowballDto } from './main-snowball.dto'; +import { UserDto } from '../user.dto'; +import { SnowballDto } from '../../../snowball/dto/snowball.dto'; import { Type } from '@nestjs/class-transformer'; -export class InfoDto { +export class ResInfoDto { @IsNotEmpty() @IsString() @ApiProperty({ @@ -20,7 +15,6 @@ export class InfoDto { readonly access_token: string; @IsNotEmpty() - @IsArray() @ValidateNested({ each: true }) @Type(() => UserDto) @ApiProperty({ @@ -30,12 +24,11 @@ export class InfoDto { readonly user: UserDto[]; @IsNotEmpty() - @IsArray() @ValidateNested({ each: true }) - @Type(() => MainSnowballDto) + @Type(() => SnowballDto) @ApiProperty({ - type: MainSnowballDto, + type: SnowballDto, description: '메인 스노우볼 정보 배열' }) - readonly main_snowball: MainSnowballDto[]; + readonly main_snowball: SnowballDto[]; } diff --git a/back/src/modules/auth/dto/message.dto.ts b/back/src/modules/message/dto/message.dto.ts similarity index 100% rename from back/src/modules/auth/dto/message.dto.ts rename to back/src/modules/message/dto/message.dto.ts diff --git a/back/src/modules/message/dto/req-create-message.dto.ts b/back/src/modules/message/dto/request/req-create-message.dto.ts similarity index 96% rename from back/src/modules/message/dto/req-create-message.dto.ts rename to back/src/modules/message/dto/request/req-create-message.dto.ts index b6520ae..1b995b5 100644 --- a/back/src/modules/message/dto/req-create-message.dto.ts +++ b/back/src/modules/message/dto/request/req-create-message.dto.ts @@ -2,7 +2,7 @@ import { IsString, IsNotEmpty, IsNumber } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; import { IsUUID } from 'class-validator'; -export class CreateMessageDto { +export class ReqCreateMessageDto { @IsNotEmpty() @IsUUID('4') @ApiProperty({ type: String, description: '스노우볼 uuid' }) diff --git a/back/src/modules/message/dto/req-delete-message.dto.ts b/back/src/modules/message/dto/request/req-delete-message.dto.ts similarity index 87% rename from back/src/modules/message/dto/req-delete-message.dto.ts rename to back/src/modules/message/dto/request/req-delete-message.dto.ts index 62b48aa..82f2662 100644 --- a/back/src/modules/message/dto/req-delete-message.dto.ts +++ b/back/src/modules/message/dto/request/req-delete-message.dto.ts @@ -1,7 +1,7 @@ import { IsNumber, IsNotEmpty } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -export class DeleteMessageDto { +export class ReqDeleteMessageDto { @IsNumber() @IsNotEmpty() @ApiProperty({ type: Number, description: '메세지 id' }) diff --git a/back/src/modules/message/dto/res-create-message.dto.ts b/back/src/modules/message/dto/response/res-create-message.dto.ts similarity index 92% rename from back/src/modules/message/dto/res-create-message.dto.ts rename to back/src/modules/message/dto/response/res-create-message.dto.ts index 18ee020..4e3931c 100644 --- a/back/src/modules/message/dto/res-create-message.dto.ts +++ b/back/src/modules/message/dto/response/res-create-message.dto.ts @@ -1,7 +1,7 @@ import { IsString, IsNotEmpty } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -export class CreateMessageDto { +export class ResCreateMessageDto { @IsString() @IsNotEmpty() @ApiProperty({ diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index b728e2d..b36abe8 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -1,7 +1,7 @@ import { Controller, Post, Delete, Body, Param } from '@nestjs/common'; import { MessageService } from './message.service'; -import { CreateMessageDto } from './dto/req-create-message.dto'; -import { DeleteMessageDto } from './dto/req-delete-message.dto'; +import { CreateMessageDto } from './dto/request/req-create-message.dto'; +import { DeleteMessageDto } from './dto/request/req-delete-message.dto'; import { ApiBody, ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; @ApiTags('Message API') diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index a62b7dc..096dc17 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { CreateMessageDto } from './dto/req-create-message.dto'; -import { DeleteMessageDto } from './dto/req-delete-message.dto'; +import { CreateMessageDto } from './dto/request/req-create-message.dto'; +import { DeleteMessageDto } from './dto/request/req-delete-message.dto'; import { MessageEntity } from './entity/message.entity'; @Injectable() diff --git a/back/src/modules/snowball/dto/req-create-snowball.dto.ts b/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts similarity index 89% rename from back/src/modules/snowball/dto/req-create-snowball.dto.ts rename to back/src/modules/snowball/dto/request/req-create-snowball.dto.ts index 31b480c..e3d9267 100644 --- a/back/src/modules/snowball/dto/req-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts @@ -3,16 +3,14 @@ import { IsNumber, IsNotEmpty, IsBoolean, - IsArray, ValidateNested } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; -import { DecorationSnowballDto } from './decoration-snowball.dto'; +import { DecorationSnowballDto } from '../decoration-snowball.dto'; -export class CreateSnowballDto { +export class ReqCreateSnowballDto { @IsNotEmpty() - @IsArray() @ValidateNested({ each: true }) @Type(() => DecorationSnowballDto) @ApiProperty({ diff --git a/back/src/modules/snowball/dto/req-update-decoration.dto.ts b/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts similarity index 79% rename from back/src/modules/snowball/dto/req-update-decoration.dto.ts rename to back/src/modules/snowball/dto/request/req-update-decoration.dto.ts index 97ea2ed..9c33e84 100644 --- a/back/src/modules/snowball/dto/req-update-decoration.dto.ts +++ b/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts @@ -1,20 +1,14 @@ -import { - IsUUID, - IsNotEmpty, - ValidateNested, - IsArray -} from '@nestjs/class-validator'; +import { IsUUID, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; import { DecorationSnowballDto } from './decoration-snowball.dto'; -export class UpdateSnowballDto { +export class ReqUpdateSnowballDecoDto { @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) @IsUUID('4') snowball_uuid: string; @IsNotEmpty() - @IsArray() @ValidateNested({ each: true }) @Type(() => DecorationSnowballDto) @ApiProperty({ diff --git a/back/src/modules/snowball/dto/req-update-snowball.dto.ts b/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts similarity index 95% rename from back/src/modules/snowball/dto/req-update-snowball.dto.ts rename to back/src/modules/snowball/dto/request/req-update-snowball.dto.ts index 0131269..f790222 100644 --- a/back/src/modules/snowball/dto/req-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts @@ -6,7 +6,7 @@ import { } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -export class UpdateSnowballDto { +export class ReqUpdateSnowballDto { @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) @IsUUID('4') snowball_uuid: string; diff --git a/back/src/modules/snowball/dto/res-create-snowball.dto.ts b/back/src/modules/snowball/dto/response/res-create-snowball.dto.ts similarity index 100% rename from back/src/modules/snowball/dto/res-create-snowball.dto.ts rename to back/src/modules/snowball/dto/response/res-create-snowball.dto.ts diff --git a/back/src/modules/snowball/dto/res-update-decoration.dto.ts b/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts similarity index 79% rename from back/src/modules/snowball/dto/res-update-decoration.dto.ts rename to back/src/modules/snowball/dto/response/res-update-decoration.dto.ts index 1dbb90b..5673a9b 100644 --- a/back/src/modules/snowball/dto/res-update-decoration.dto.ts +++ b/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts @@ -1,20 +1,14 @@ -import { - IsUUID, - IsNotEmpty, - ValidateNested, - IsArray -} from '@nestjs/class-validator'; +import { IsUUID, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; import { DecorationSnowballDto } from './decoration-snowball.dto'; -export class UpdateSnowballDto { +export class ResUpdateSnowballDto { @ApiProperty({ format: 'uuid', description: '변경된 스노우볼 UUID' }) @IsUUID('4') snowball_uuid: string; @IsNotEmpty() - @IsArray() @ValidateNested({ each: true }) @Type(() => DecorationSnowballDto) @ApiProperty({ diff --git a/back/src/modules/snowball/dto/res-update-snowball.dto.ts b/back/src/modules/snowball/dto/response/res-update-snowball.dto.ts similarity index 100% rename from back/src/modules/snowball/dto/res-update-snowball.dto.ts rename to back/src/modules/snowball/dto/response/res-update-snowball.dto.ts diff --git a/back/src/modules/auth/dto/main-snowball.dto.ts b/back/src/modules/snowball/dto/snowball.dto.ts similarity index 92% rename from back/src/modules/auth/dto/main-snowball.dto.ts rename to back/src/modules/snowball/dto/snowball.dto.ts index e42745e..d66802f 100644 --- a/back/src/modules/auth/dto/main-snowball.dto.ts +++ b/back/src/modules/snowball/dto/snowball.dto.ts @@ -3,15 +3,14 @@ import { IsUUID, IsBoolean, IsNotEmpty, - IsArray, ValidateNested } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; import { DecorationSnowballDto } from '../../snowball/dto/decoration-snowball.dto'; -import { MessageDto } from './message.dto'; +import { MessageDto } from '../../message/dto/message.dto'; -export class MainSnowballDto { +export class SnowballDto { @IsString() @IsNotEmpty() @ApiProperty({ type: String, description: '스노우볼 제목' }) @@ -39,7 +38,6 @@ export class MainSnowballDto { readonly message_count_private: boolean; @IsNotEmpty() - @IsArray() @ValidateNested({ each: true }) @Type(() => DecorationSnowballDto) @ApiProperty({ @@ -49,7 +47,6 @@ export class MainSnowballDto { readonly deco_list: DecorationSnowballDto[]; @IsNotEmpty() - @IsArray() @ValidateNested({ each: true }) @Type(() => MessageDto) @ApiProperty({ diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index d424a58..4a403fb 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -7,10 +7,10 @@ import { ApiCreatedResponse, ApiResponse } from '@nestjs/swagger'; -import { CreateSnowballDto } from './dto/req-create-snowball.dto'; -import { UpdateSnowballDto } from './dto/req-update-snowball.dto'; -import { ResCreateSnowballDto } from './dto/res-create-snowball.dto'; -import { ResUpdateSnowballDto } from './dto/res-update-snowball.dto'; +import { ReqCreateSnowballDto } from './dto/request/req-create-snowball.dto'; +import { ReqUpdateSnowballDto } from './dto/request/req-update-snowball.dto'; +import { ResCreateSnowballDto } from './dto/response/res-create-snowball.dto'; +import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; @ApiTags('Snowball API') @Controller('snowball') @@ -26,8 +26,8 @@ export class SnowballController { description: '스노우볼 생성 성공', type: ResCreateSnowballDto }) - @ApiBody({ type: CreateSnowballDto }) - createSnowball(@Body() createSnowballDto: CreateSnowballDto) { + @ApiBody({ type: ReqCreateSnowballDto }) + createSnowball(@Body() createSnowballDto: ReqCreateSnowballDto) { return createSnowballDto; } @@ -41,8 +41,8 @@ export class SnowballController { summary: '스노우볼 설정 업데이트 API', description: '스노우볼에의 정보를 업데이트 해줍니다.' }) - @ApiBody({ type: UpdateSnowballDto }) - updateSnowball(@Body() updateSnowballDto: UpdateSnowballDto) { + @ApiBody({ type: ReqUpdateSnowballDto }) + updateSnowball(@Body() updateSnowballDto: ReqUpdateSnowballDto) { updateSnowballDto; } } diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index b304d07..79e4f98 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { SnowballEntity } from './entity/snowball.entity'; -import { CreateSnowballDto } from './dto/req-create-snowball.dto'; -import { UpdateSnowballDto } from './dto/req-update-snowball.dto'; +import { ReqCreateSnowballDto } from './dto/request/req-create-snowball.dto'; +import { ReqUpdateSnowballDto } from './dto/request/req-update-snowball.dto'; @Injectable() export class SnowballService { @@ -12,12 +12,12 @@ export class SnowballService { private readonly snowballRepository: Repository ) {} async createSnowball( - createSnowballDto: CreateSnowballDto + createSnowballDto: ReqCreateSnowballDto ): Promise { const snowball = this.snowballRepository.create(createSnowballDto); return await this.snowballRepository.save(snowball); } - async updateSnowball(updateSnowballDto: UpdateSnowballDto): Promise { + async updateSnowball(updateSnowballDto: ReqUpdateSnowballDto): Promise { await this.snowballRepository.delete(updateSnowballDto.snowball_uuid); } } From 2bff75647d9bc0bb9e5aff8a39f9f9eeea062e25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Mon, 20 Nov 2023 02:44:15 +0900 Subject: [PATCH 050/185] =?UTF-8?q?fix:=20=ED=8C=8C=EC=9D=BC=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.controller.ts | 12 ++++++------ back/src/modules/message/message.service.ts | 8 ++++---- .../dto/request/req-update-decoration.dto.ts | 2 +- .../dto/response/res-update-decoration.dto.ts | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index b36abe8..1179cbd 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -1,7 +1,7 @@ import { Controller, Post, Delete, Body, Param } from '@nestjs/common'; import { MessageService } from './message.service'; -import { CreateMessageDto } from './dto/request/req-create-message.dto'; -import { DeleteMessageDto } from './dto/request/req-delete-message.dto'; +import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; +import { ReqDeleteMessageDto } from './dto/request/req-delete-message.dto'; import { ApiBody, ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; @ApiTags('Message API') @@ -14,9 +14,9 @@ export class MessageController { summary: '메세지 생성 API', description: '스노우볼에 메세지를 생성합니다.' }) - @ApiBody({ type: CreateMessageDto }) + @ApiBody({ type: ReqCreateMessageDto }) @ApiResponse({ status: 201, description: 'Created' }) - createMessage(@Body() createMessageDto: CreateMessageDto) { + createMessage(@Body() createMessageDto: ReqCreateMessageDto) { return this.messageService.createMessage(createMessageDto); } @@ -25,9 +25,9 @@ export class MessageController { summary: '메세지 삭제 API', description: '스노우볼에서 특정 메세지를 삭제합니다.' }) - @ApiBody({ type: DeleteMessageDto }) + @ApiBody({ type: ReqDeleteMessageDto }) @ApiResponse({ status: 204, description: 'No Content' }) - deleteMessage(@Param() deleteMessageDto: DeleteMessageDto) { + deleteMessage(@Param() deleteMessageDto: ReqDeleteMessageDto) { this.messageService.deleteMessage(deleteMessageDto); } } diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 096dc17..a95efee 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { CreateMessageDto } from './dto/request/req-create-message.dto'; -import { DeleteMessageDto } from './dto/request/req-delete-message.dto'; +import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; +import { ReqDeleteMessageDto } from './dto/request/req-delete-message.dto'; import { MessageEntity } from './entity/message.entity'; @Injectable() @@ -12,7 +12,7 @@ export class MessageService { private readonly messageRepository: Repository ) {} async createMessage( - createMessageDto: CreateMessageDto + createMessageDto: ReqCreateMessageDto ): Promise { const messageEntity = this.messageRepository.create({ snowball_id: createMessageDto.snowball_id, @@ -23,7 +23,7 @@ export class MessageService { }); return await this.messageRepository.save(messageEntity); } - async deleteMessage(deleteMessageDto: DeleteMessageDto): Promise { + async deleteMessage(deleteMessageDto: ReqDeleteMessageDto): Promise { await this.messageRepository.delete(deleteMessageDto.message_id); } diff --git a/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts b/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts index 9c33e84..88f18a3 100644 --- a/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts +++ b/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts @@ -1,7 +1,7 @@ import { IsUUID, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; -import { DecorationSnowballDto } from './decoration-snowball.dto'; +import { DecorationSnowballDto } from '../decoration-snowball.dto'; export class ReqUpdateSnowballDecoDto { @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) diff --git a/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts b/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts index 5673a9b..c212a94 100644 --- a/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts +++ b/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts @@ -1,9 +1,9 @@ import { IsUUID, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; -import { DecorationSnowballDto } from './decoration-snowball.dto'; +import { DecorationSnowballDto } from '../decoration-snowball.dto'; -export class ResUpdateSnowballDto { +export class ResUpdateSnowballDecoDto { @ApiProperty({ format: 'uuid', description: '변경된 스노우볼 UUID' }) @IsUUID('4') snowball_uuid: string; From 453c686bd21013ce53f7dc82c2c9bf31f858777c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Mon, 20 Nov 2023 03:29:15 +0900 Subject: [PATCH 051/185] =?UTF-8?q?feat:=20auth=20api=20response=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/app.module.ts | 3 +- back/src/modules/auth/auth.controller.ts | 67 +++++++++++------ back/src/modules/auth/auth.module.ts | 8 +- back/src/modules/auth/auth.service.ts | 74 +++++++++++++++++++ back/src/modules/message/dto/message.dto.ts | 6 +- .../snowball/dto/decoration-snowball.dto.ts | 2 +- 6 files changed, 127 insertions(+), 33 deletions(-) create mode 100644 back/src/modules/auth/auth.service.ts diff --git a/back/src/app.module.ts b/back/src/app.module.ts index 2dfd366..a72e16d 100644 --- a/back/src/app.module.ts +++ b/back/src/app.module.ts @@ -2,14 +2,13 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { AppController } from './app.controller'; import { AppService } from './app.service'; -import { AuthController } from './modules/auth/auth.controller'; import { AuthModule } from './modules/auth/auth.module'; import { SnowballModule } from './modules/snowball/snowball.module'; import typeOrmConfig from './config/ormconfig'; @Module({ imports: [TypeOrmModule.forRoot(typeOrmConfig), AuthModule, SnowballModule], - controllers: [AppController, AuthController], + controllers: [AppController], providers: [AppService] }) export class AppModule {} diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index a0a9bf1..3c7215f 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -1,15 +1,13 @@ import { Controller, Get, Req, Res, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; -import { - ApiTags, - ApiOperation, - ApiExcludeEndpoint, - ApiResponse -} from '@nestjs/swagger'; +import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; +import { ResInfoDto } from './dto/response/res-info.dto'; +import { AuthService } from './auth.service'; @ApiTags('Oauth API') @Controller('auth') export class AuthController { + constructor(private readonly authService: AuthService) {} @Get('google') @ApiOperation({ summary: 'Google 로그인 요청 API', @@ -17,23 +15,30 @@ export class AuthController { }) @ApiResponse({ status: 200, - description: `'https://mysnowball.kr'로 리다이렉트` + description: `'https://mysnowball.kr/auth/google/redirect'로 GET요청을 보냅니다.` }) @ApiResponse({ status: 400, - description: `'https://mysnowball.kr/failure'으로 리다이렉트` + description: `'https://mysnowball.kr/auth/google/failure'로 GET요청을 보냅니다.` }) @UseGuards(AuthGuard('google')) async googleLogin(): Promise {} @Get('google/redirect') - @ApiExcludeEndpoint() @UseGuards(AuthGuard('google')) + @ApiResponse({ + status: 200, + description: 'Google 로그인 성공', + type: ResInfoDto + }) + @ApiResponse({ + status: 500, + description: 'Internal Server Error' + }) async googleLoginCallback(@Req() req, @Res() res): Promise { const profile: string = req.user.profile; - if (profile) { - res.redirect('http://localhost:3000/'); - } else res.redirect('http://localhost:3000/failure'); + const result = this.authService.createInfo(profile); + res.status(200).json(result); } @Get('naver') @@ -43,23 +48,30 @@ export class AuthController { }) @ApiResponse({ status: 200, - description: `'https://mysnowball.kr'으로 리다이렉트` + description: `'https://mysnowball.kr/auth/naver/redirect'로 GET요청을 보냅니다.` }) @ApiResponse({ status: 400, - description: `'https://mysnowball.kr/failure'으로 리다이렉트` + description: `'https://mysnowball.kr/auth/naver/failure'로 GET요청을 보냅니다.` }) @UseGuards(AuthGuard('naver')) async naverLogin(): Promise {} @Get('naver/redirect') - @ApiExcludeEndpoint() @UseGuards(AuthGuard('naver')) + @ApiResponse({ + status: 200, + description: 'Naver 로그인 성공', + type: ResInfoDto + }) + @ApiResponse({ + status: 500, + description: 'Internal Server Error' + }) async naverLoginCallBack(@Req() req, @Res() res): Promise { const profile: string = req.user.profile; - if (profile) { - res.redirect('http://localhost:3000/'); - } else res.redirect('http://localhost:3000/failure'); + const result = this.authService.createInfo(profile); + res.status(200).json(result); } @Get('kakao') @@ -69,22 +81,29 @@ export class AuthController { }) @ApiResponse({ status: 200, - description: `'https://mysnowball.kr'으로 리다이렉트` + description: `'https://mysnowball.kr/auth/kakao/redirect'로 GET요청을 보냅니다.` }) @ApiResponse({ status: 400, - description: `'https://mysnowball.kr/failure'으로 리다이렉트` + description: `'https://mysnowball.kr/auth/kakao/failure'로 GET요청을 보냅니다.` }) @UseGuards(AuthGuard('kakao')) async kakaoLogin(): Promise {} @Get('kakao/redirect') - @ApiExcludeEndpoint() @UseGuards(AuthGuard('kakao')) + @ApiResponse({ + status: 200, + description: 'Kakao 로그인 성공', + type: ResInfoDto + }) + @ApiResponse({ + status: 500, + description: 'Internal Server Error' + }) async kakaoLoginCallBack(@Req() req, @Res() res): Promise { const profile: string = req.user.profile; - if (profile) { - res.redirect('http://localhost:3000/'); - } else res.redirect('http://localhost:3000/failure'); + const result = this.authService.createInfo(profile); + res.status(200).json(result); } } diff --git a/back/src/modules/auth/auth.module.ts b/back/src/modules/auth/auth.module.ts index 393b2e0..839971e 100644 --- a/back/src/modules/auth/auth.module.ts +++ b/back/src/modules/auth/auth.module.ts @@ -4,10 +4,16 @@ import { NaverAuthStrategy } from './naver-auth.strategy'; import { KakaoAuthStrategy } from './kakao-auth.strategy'; import { AuthController } from './auth.controller'; import { PassportModule } from '@nestjs/passport'; +import { AuthService } from './auth.service'; @Module({ imports: [PassportModule], - providers: [GoogleAuthStrategy, NaverAuthStrategy, KakaoAuthStrategy], + providers: [ + GoogleAuthStrategy, + NaverAuthStrategy, + KakaoAuthStrategy, + AuthService + ], controllers: [AuthController] }) export class AuthModule {} diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts new file mode 100644 index 0000000..5cf95ce --- /dev/null +++ b/back/src/modules/auth/auth.service.ts @@ -0,0 +1,74 @@ +import { Injectable, UnauthorizedException } from '@nestjs/common'; +import { ResInfoDto } from './dto/response/res-info.dto'; +import { UserDto } from './dto/user.dto'; +import { SnowballDto } from '../snowball/dto/snowball.dto'; +@Injectable() +export class AuthService { + constructor() {} + + async createInfo(profile: any): Promise { + if (profile) { + // Example data, replace with actual data from your logic + const access_token = 'your-access-token'; + const userDto: UserDto = { + name: '김찬우', + id: 'Oauth에서 주는 값', + snowball_count: 3, + snowball_list: [ + '32413434-32a2-2342-3242-3g23-413oye3', + '32413434-32a2-2342-3242-3g23-413oye3', + '32413434-32a2-2342-3242-3g23-413oye3' + ], + message_count: 123 + }; + const mainSnowballDto: SnowballDto = { + title: '나만의 스노우볼1', + uuid: '32413434-32a2-2342-3242-3g23-413oye3', + message_private: null, + message_count_private: null, + deco_list: [ + { + decoration_id: 15, + decoration_color: '#FFFFFF', + location: 13 + }, + { + decoration_id: 12, + decoration_color: '#FFFFFF', + location: 14 + } + ], + message_list: [ + { + id: 1, + decoration_id: 15, + decoration_color: '#FFFFFF', + content: '편지 내용', + sender: '널 좋아하는 사람', + opened: null, + created: new Date('2023-12-30T17:35:31Z') + }, + { + id: 2, + decoration_id: 15, + decoration_color: '#FFFFFF', + content: '편지 내용', + sender: '찬우를 사랑하는 사람', + opened: null, + created: new Date('2023-12-30T17:35:31Z') + } + ] + }; + + const resInfoDto: ResInfoDto = { + access_token, + user: [userDto], + main_snowball: [mainSnowballDto] + }; + + return resInfoDto; + } else { + throw new UnauthorizedException('Failed to authenticate with Google'); + } + } +} diff --git a/back/src/modules/message/dto/message.dto.ts b/back/src/modules/message/dto/message.dto.ts index aff438b..5df472b 100644 --- a/back/src/modules/message/dto/message.dto.ts +++ b/back/src/modules/message/dto/message.dto.ts @@ -6,10 +6,6 @@ export class MessageDto { @ApiProperty({ type: Number, description: '메시지 ID' }) readonly id: number; - @IsString() - @ApiProperty({ type: String, description: '스노우볼 ID' }) - readonly snowball_id: string; - @IsNumber() @ApiProperty({ type: Number, description: '데코레이션 ID' }) readonly decoration_id: number; @@ -32,5 +28,5 @@ export class MessageDto { @IsDate() @ApiProperty({ type: Date, description: '생성 날짜' }) - readonly created_at: Date; + readonly created: Date; } diff --git a/back/src/modules/snowball/dto/decoration-snowball.dto.ts b/back/src/modules/snowball/dto/decoration-snowball.dto.ts index d53f1a9..f43b34c 100644 --- a/back/src/modules/snowball/dto/decoration-snowball.dto.ts +++ b/back/src/modules/snowball/dto/decoration-snowball.dto.ts @@ -5,7 +5,7 @@ export class DecorationSnowballDto { @IsNumber() @IsNotEmpty() @ApiProperty({ type: Number, description: '장식 종류' }) - readonly deco_id: number; + readonly decoration_id: number; @IsString() @IsNotEmpty() From 4893228641183b7edd30ace12d10d786d4829332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Mon, 20 Nov 2023 03:52:47 +0900 Subject: [PATCH 052/185] =?UTF-8?q?feat:=20message=20delete=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.controller.ts | 6 +++--- back/src/modules/message/message.controller.ts | 8 ++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index 3c7215f..060caab 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -28,7 +28,7 @@ export class AuthController { @UseGuards(AuthGuard('google')) @ApiResponse({ status: 200, - description: 'Google 로그인 성공', + description: 'Google 로그인 성공 및 Info 반환', type: ResInfoDto }) @ApiResponse({ @@ -61,7 +61,7 @@ export class AuthController { @UseGuards(AuthGuard('naver')) @ApiResponse({ status: 200, - description: 'Naver 로그인 성공', + description: 'Naver 로그인 성공 및 Info 반환', type: ResInfoDto }) @ApiResponse({ @@ -94,7 +94,7 @@ export class AuthController { @UseGuards(AuthGuard('kakao')) @ApiResponse({ status: 200, - description: 'Kakao 로그인 성공', + description: 'Kakao 로그인 성공 및 Info 반환', type: ResInfoDto }) @ApiResponse({ diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 1179cbd..6a66a58 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -3,6 +3,7 @@ import { MessageService } from './message.service'; import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; import { ReqDeleteMessageDto } from './dto/request/req-delete-message.dto'; import { ApiBody, ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; +import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; @ApiTags('Message API') @Controller('message') @@ -15,7 +16,11 @@ export class MessageController { description: '스노우볼에 메세지를 생성합니다.' }) @ApiBody({ type: ReqCreateMessageDto }) - @ApiResponse({ status: 201, description: 'Created' }) + @ApiResponse({ + status: 201, + description: 'Created', + type: ResCreateMessageDto + }) createMessage(@Body() createMessageDto: ReqCreateMessageDto) { return this.messageService.createMessage(createMessageDto); } @@ -25,7 +30,6 @@ export class MessageController { summary: '메세지 삭제 API', description: '스노우볼에서 특정 메세지를 삭제합니다.' }) - @ApiBody({ type: ReqDeleteMessageDto }) @ApiResponse({ status: 204, description: 'No Content' }) deleteMessage(@Param() deleteMessageDto: ReqDeleteMessageDto) { this.messageService.deleteMessage(deleteMessageDto); From 26fbbd3a85083548653b21c28dfdb8a5190191f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Mon, 20 Nov 2023 04:56:45 +0900 Subject: [PATCH 053/185] =?UTF-8?q?feat:=20message=20&=20auth=20swagger=20?= =?UTF-8?q?=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.controller.ts | 17 +++++----- back/src/modules/auth/auth.service.ts | 1 + .../dto/request/req-create-message.dto.ts | 7 ++--- .../modules/message/entity/message.entity.ts | 2 +- .../src/modules/message/message.controller.ts | 31 ++++++++++++++++--- back/src/modules/message/message.service.ts | 20 +++++++++--- .../dto/request/req-update-decoration.dto.ts | 9 +++--- .../dto/request/req-update-snowball.dto.ts | 9 +++--- back/src/modules/snowball/dto/snowball.dto.ts | 6 ++++ back/src/modules/snowball/snowball.service.ts | 2 +- test | 1 - 11 files changed, 73 insertions(+), 32 deletions(-) delete mode 160000 test diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index 060caab..59cc64b 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Get, Req, Res, UseGuards } from '@nestjs/common'; +import { Controller, Get, Req, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; import { ResInfoDto } from './dto/response/res-info.dto'; @@ -31,14 +31,15 @@ export class AuthController { description: 'Google 로그인 성공 및 Info 반환', type: ResInfoDto }) + @ApiResponse({ status: 401, description: 'Unauthorized' }) @ApiResponse({ status: 500, description: 'Internal Server Error' }) - async googleLoginCallback(@Req() req, @Res() res): Promise { + async googleLoginCallback(@Req() req): Promise { const profile: string = req.user.profile; const result = this.authService.createInfo(profile); - res.status(200).json(result); + return result; } @Get('naver') @@ -64,14 +65,15 @@ export class AuthController { description: 'Naver 로그인 성공 및 Info 반환', type: ResInfoDto }) + @ApiResponse({ status: 401, description: 'Unauthorized' }) @ApiResponse({ status: 500, description: 'Internal Server Error' }) - async naverLoginCallBack(@Req() req, @Res() res): Promise { + async naverLoginCallBack(@Req() req): Promise { const profile: string = req.user.profile; const result = this.authService.createInfo(profile); - res.status(200).json(result); + return result; } @Get('kakao') @@ -97,13 +99,14 @@ export class AuthController { description: 'Kakao 로그인 성공 및 Info 반환', type: ResInfoDto }) + @ApiResponse({ status: 401, description: 'Unauthorized' }) @ApiResponse({ status: 500, description: 'Internal Server Error' }) - async kakaoLoginCallBack(@Req() req, @Res() res): Promise { + async kakaoLoginCallBack(@Req() req): Promise { const profile: string = req.user.profile; const result = this.authService.createInfo(profile); - res.status(200).json(result); + return result; } } diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index 5cf95ce..9b9663b 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -23,6 +23,7 @@ export class AuthService { }; const mainSnowballDto: SnowballDto = { title: '나만의 스노우볼1', + id: 1, uuid: '32413434-32a2-2342-3242-3g23-413oye3', message_private: null, message_count_private: null, diff --git a/back/src/modules/message/dto/request/req-create-message.dto.ts b/back/src/modules/message/dto/request/req-create-message.dto.ts index 1b995b5..94f3427 100644 --- a/back/src/modules/message/dto/request/req-create-message.dto.ts +++ b/back/src/modules/message/dto/request/req-create-message.dto.ts @@ -1,12 +1,11 @@ import { IsString, IsNotEmpty, IsNumber } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -import { IsUUID } from 'class-validator'; export class ReqCreateMessageDto { @IsNotEmpty() - @IsUUID('4') - @ApiProperty({ type: String, description: '스노우볼 uuid' }) - readonly snowball_id: string; + @IsNumber() + @ApiProperty({ type: Number, description: '스노우볼 id' }) + readonly snowball_id: number; @IsString() @IsNotEmpty() diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 29957ee..e54f137 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -14,7 +14,7 @@ export class MessageEntity { id: number; @Column() - snowball_id: string; + snowball_id: number; @Column() decoration_id: number; diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 6a66a58..59d0236 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -1,4 +1,11 @@ -import { Controller, Post, Delete, Body, Param } from '@nestjs/common'; +import { + Controller, + Post, + Delete, + Body, + Param, + HttpCode +} from '@nestjs/common'; import { MessageService } from './message.service'; import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; import { ReqDeleteMessageDto } from './dto/request/req-delete-message.dto'; @@ -11,6 +18,7 @@ export class MessageController { constructor(private readonly messageService: MessageService) {} @Post() + @HttpCode(201) @ApiOperation({ summary: '메세지 생성 API', description: '스노우볼에 메세지를 생성합니다.' @@ -21,17 +29,30 @@ export class MessageController { description: 'Created', type: ResCreateMessageDto }) - createMessage(@Body() createMessageDto: ReqCreateMessageDto) { - return this.messageService.createMessage(createMessageDto); + @ApiResponse({ + status: 500, + description: 'Insert Fail' + }) + async createMessage( + @Body() createMessageDto: ReqCreateMessageDto + ): Promise { + const resCreateMessage = + await this.messageService.createMessage(createMessageDto); + return resCreateMessage; } @Delete(':message_id') + @HttpCode(204) @ApiOperation({ summary: '메세지 삭제 API', description: '스노우볼에서 특정 메세지를 삭제합니다.' }) @ApiResponse({ status: 204, description: 'No Content' }) - deleteMessage(@Param() deleteMessageDto: ReqDeleteMessageDto) { - this.messageService.deleteMessage(deleteMessageDto); + @ApiResponse({ + status: 500, + description: 'Delete Fail' + }) + async deleteMessage(@Param() deleteMessageDto: ReqDeleteMessageDto) { + await this.messageService.deleteMessage(deleteMessageDto); } } diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index a95efee..8b197fd 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -4,6 +4,7 @@ import { Repository } from 'typeorm'; import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; import { ReqDeleteMessageDto } from './dto/request/req-delete-message.dto'; import { MessageEntity } from './entity/message.entity'; +import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; @Injectable() export class MessageService { @@ -13,15 +14,24 @@ export class MessageService { ) {} async createMessage( createMessageDto: ReqCreateMessageDto - ): Promise { + ): Promise { const messageEntity = this.messageRepository.create({ snowball_id: createMessageDto.snowball_id, - decoration_id: createMessageDto.decoration_id, + sender: createMessageDto.sender, content: createMessageDto.content, - sender: createMessageDto.sender - // opened와 created_at은 자동으로 설정됩니다. + decoration_id: createMessageDto.decoration_id, + decoration_color: createMessageDto.decoration_color + // opened와 created_at은 자동으로 설정 }); - return await this.messageRepository.save(messageEntity); + const savedMessage = await this.messageRepository.save(messageEntity); + + // 이 부분에서 필터링 로직을 작성 + const resCreateMessage: ResCreateMessageDto = { + sender: savedMessage.sender, + content: savedMessage.content + }; + + return resCreateMessage; } async deleteMessage(deleteMessageDto: ReqDeleteMessageDto): Promise { await this.messageRepository.delete(deleteMessageDto.message_id); diff --git a/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts b/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts index 88f18a3..6724841 100644 --- a/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts +++ b/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts @@ -1,12 +1,13 @@ -import { IsUUID, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; +import { IsNumber, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; import { DecorationSnowballDto } from '../decoration-snowball.dto'; export class ReqUpdateSnowballDecoDto { - @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) - @IsUUID('4') - snowball_uuid: string; + @IsNotEmpty() + @IsNumber() + @ApiProperty({ type: Number, description: '스노우볼 id' }) + readonly snowball_id: number; @IsNotEmpty() @ValidateNested({ each: true }) diff --git a/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts b/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts index f790222..1a809fc 100644 --- a/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts @@ -1,15 +1,16 @@ import { IsString, - IsUUID, + IsNumber, IsNotEmpty, IsBoolean } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class ReqUpdateSnowballDto { - @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) - @IsUUID('4') - snowball_uuid: string; + @IsNotEmpty() + @IsNumber() + @ApiProperty({ type: Number, description: '스노우볼 id' }) + readonly snowball_id: number; @IsString() @IsNotEmpty() diff --git a/back/src/modules/snowball/dto/snowball.dto.ts b/back/src/modules/snowball/dto/snowball.dto.ts index d66802f..44cbec9 100644 --- a/back/src/modules/snowball/dto/snowball.dto.ts +++ b/back/src/modules/snowball/dto/snowball.dto.ts @@ -2,6 +2,7 @@ import { IsString, IsUUID, IsBoolean, + IsNumber, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; @@ -16,6 +17,11 @@ export class SnowballDto { @ApiProperty({ type: String, description: '스노우볼 제목' }) readonly title: string; + @IsNotEmpty() + @IsNumber() + @ApiProperty({ type: Number, description: '스노우볼 id' }) + readonly id: number; + @IsUUID('4') @IsNotEmpty() @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 79e4f98..91b0b4c 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -18,6 +18,6 @@ export class SnowballService { return await this.snowballRepository.save(snowball); } async updateSnowball(updateSnowballDto: ReqUpdateSnowballDto): Promise { - await this.snowballRepository.delete(updateSnowballDto.snowball_uuid); + await this.snowballRepository.delete(updateSnowballDto.snowball_id); } } diff --git a/test b/test deleted file mode 160000 index 38a4089..0000000 --- a/test +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 38a4089437755bfca532f4eba4a83ae5a5c443d9 From b6d06d64599f521f571673f01deb32fee7baf733 Mon Sep 17 00:00:00 2001 From: peageon Date: Mon, 20 Nov 2023 13:09:54 +0900 Subject: [PATCH 054/185] =?UTF-8?q?feat:=20res-create-snowball=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20snowball.dto=20=EB=A1=9C=20=EB=8C=80=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/.DS_Store | Bin 0 -> 6148 bytes .../dto/request/req-create-snowball.dto.ts | 8 -------- .../dto/request/req-update-snowball.dto.ts | 8 -------- .../dto/response/res-create-snowball.dto.ts | 15 --------------- .../dto/response/res-update-snowball.dto.ts | 7 ------- back/src/modules/snowball/dto/snowball.dto.ts | 1 - back/src/modules/snowball/snowball.controller.ts | 4 ++-- 7 files changed, 2 insertions(+), 41 deletions(-) create mode 100644 back/.DS_Store delete mode 100644 back/src/modules/snowball/dto/response/res-create-snowball.dto.ts diff --git a/back/.DS_Store b/back/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..8757d249b864fe2623d382833d1feefd79387f04 GIT binary patch literal 6148 zcmeHK%}T>S5Z<*_HxwZUg&qT53${iC@e*Qv0V8@)sfj5XjMYb>kIiLK94iI z8?czOh@FAmZ+>^PA7ph!z7#LsvwD{kaBySWU;J#InUxk)do5sEX$hM{l&s{-GOs78Z8IT;^c4$x_i7_ zT4Hbi;PhhhoW5l8P1DJNZ6!Mf8+ZrBtmZYyvs7k};Ayg(EJ9*{7$63Sf%RsL>R=kUw4KJr&f$RY-a zfq%vT?~a494~sHq>yPE(S?fT%hlYZAH7X#WuUrDaz MessageDto) @ApiProperty({ diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index 4a403fb..b19298f 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -9,7 +9,7 @@ import { } from '@nestjs/swagger'; import { ReqCreateSnowballDto } from './dto/request/req-create-snowball.dto'; import { ReqUpdateSnowballDto } from './dto/request/req-update-snowball.dto'; -import { ResCreateSnowballDto } from './dto/response/res-create-snowball.dto'; +import { SnowballDto } from './dto/snowball.dto'; import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; @ApiTags('Snowball API') @@ -24,7 +24,7 @@ export class SnowballController { }) @ApiCreatedResponse({ description: '스노우볼 생성 성공', - type: ResCreateSnowballDto + type: SnowballDto }) @ApiBody({ type: ReqCreateSnowballDto }) createSnowball(@Body() createSnowballDto: ReqCreateSnowballDto) { From 10bd0be90bd863e31a0d71c541fde02e2543d716 Mon Sep 17 00:00:00 2001 From: peageon Date: Mon, 20 Nov 2023 18:32:46 +0900 Subject: [PATCH 055/185] =?UTF-8?q?feat:=20=EC=8A=A4=EB=85=B8=EC=9A=B0?= =?UTF-8?q?=EB=B3=BC=20api=20=EB=A1=9C=EC=A7=81=EB=93=A4=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=EB=B2=A0=EC=9D=B4=EC=8A=A4=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=EC=9E=91=EC=97=85=ED=95=98=EA=B3=A0=20=EB=AA=85=EC=84=B8?= =?UTF-8?q?=EB=8C=80=EB=A1=9C=20=EB=B0=98=ED=99=98=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.service.ts | 2 +- .../dto/response/res-update-decoration.dto.ts | 9 +- back/src/modules/snowball/dto/snowball.dto.ts | 8 -- .../snowball/entity/snowball.entity.ts | 3 - .../modules/snowball/snowball.controller.ts | 43 +++++- back/src/modules/snowball/snowball.module.ts | 11 +- back/src/modules/snowball/snowball.service.ts | 126 +++++++++++++++++- 7 files changed, 176 insertions(+), 26 deletions(-) diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index 9b9663b..26b119e 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -26,7 +26,7 @@ export class AuthService { id: 1, uuid: '32413434-32a2-2342-3242-3g23-413oye3', message_private: null, - message_count_private: null, + // message_count_private: null, deco_list: [ { decoration_id: 15, diff --git a/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts b/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts index c212a94..afea3eb 100644 --- a/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts +++ b/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts @@ -1,12 +1,13 @@ -import { IsUUID, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; +import { IsNotEmpty, IsNumber, ValidateNested } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; import { DecorationSnowballDto } from '../decoration-snowball.dto'; export class ResUpdateSnowballDecoDto { - @ApiProperty({ format: 'uuid', description: '변경된 스노우볼 UUID' }) - @IsUUID('4') - snowball_uuid: string; + @IsNotEmpty() + @IsNumber() + @ApiProperty({ type: Number, description: '스노우볼 id' }) + readonly snowball_id: number; @IsNotEmpty() @ValidateNested({ each: true }) diff --git a/back/src/modules/snowball/dto/snowball.dto.ts b/back/src/modules/snowball/dto/snowball.dto.ts index 21dcb06..f520bfd 100644 --- a/back/src/modules/snowball/dto/snowball.dto.ts +++ b/back/src/modules/snowball/dto/snowball.dto.ts @@ -35,14 +35,6 @@ export class SnowballDto { }) readonly message_private: boolean; - @IsBoolean() - @IsNotEmpty() - @ApiProperty({ - type: Boolean, - description: '스노우볼 속 메시지 갯수 비공개 여부' - }) - readonly message_count_private: boolean; - @IsNotEmpty() @ValidateNested({ each: true }) @Type(() => DecorationSnowballDto) diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index f72e71a..6e6a64d 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -34,9 +34,6 @@ export class SnowballEntity { @CreateDateColumn({ nullable: true, default: null }) message_private: Date | null; - @CreateDateColumn({ nullable: true, default: null }) - message_count_private: Date | null; - @ManyToOne(() => UserEntity, user => user.snowballs) @JoinColumn({ name: 'user_id' }) user: UserEntity; diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index b19298f..0b1734d 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Post, Put, Body } from '@nestjs/common'; +import { Controller, Post, Put, Body, Param, Get } from '@nestjs/common'; import { SnowballService } from './snowball.service'; import { ApiBody, @@ -11,6 +11,8 @@ import { ReqCreateSnowballDto } from './dto/request/req-create-snowball.dto'; import { ReqUpdateSnowballDto } from './dto/request/req-update-snowball.dto'; import { SnowballDto } from './dto/snowball.dto'; import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; +import { ReqUpdateSnowballDecoDto } from './dto/request/req-update-decoration.dto'; +import { ResUpdateSnowballDecoDto } from './dto/response/res-update-decoration.dto'; @ApiTags('Snowball API') @Controller('snowball') @@ -28,7 +30,26 @@ export class SnowballController { }) @ApiBody({ type: ReqCreateSnowballDto }) createSnowball(@Body() createSnowballDto: ReqCreateSnowballDto) { - return createSnowballDto; + const snowball = this.snowballService.createSnowball(createSnowballDto); + return snowball; + } + + @Put() + @ApiResponse({ + status: 200, + description: '스노우볼 데코레이션 업데이트 성공', + type: ResUpdateSnowballDecoDto + }) + @ApiOperation({ + summary: '스노우볼 데코레이션 업데이트 API', + description: '스노우볼의 데코레이션들을 업데이트 해줍니다.' + }) + @ApiBody({ type: ReqUpdateSnowballDecoDto }) + updateSnowballDecor(@Body() updateSnowballDecoDto: ReqUpdateSnowballDecoDto) { + const snowballDecoration = this.snowballService.updateSnowballDeco( + updateSnowballDecoDto + ); + return snowballDecoration; } @Put() @@ -43,6 +64,22 @@ export class SnowballController { }) @ApiBody({ type: ReqUpdateSnowballDto }) updateSnowball(@Body() updateSnowballDto: ReqUpdateSnowballDto) { - updateSnowballDto; + const snowball = this.snowballService.updateSnowball(updateSnowballDto); + return snowball; + } + + @Get('/:snowball_id/messages') + @ApiResponse({ + status: 200, + description: '스노우볼 메시지들 조회 성공', + type: SnowballDto + }) + @ApiOperation({ + summary: '스노우볼 메시지들 조회 API', + description: '스노우볼에 속한 메시지들을 조회합니다.' + }) + async getMessages(@Param('snowball_id') snowball_id: number) { + const messages = await this.snowballService.getMessages(snowball_id); + return messages; } } diff --git a/back/src/modules/snowball/snowball.module.ts b/back/src/modules/snowball/snowball.module.ts index 7e72f70..e8441ea 100644 --- a/back/src/modules/snowball/snowball.module.ts +++ b/back/src/modules/snowball/snowball.module.ts @@ -4,9 +4,18 @@ import { SnowballService } from './snowball.service'; import { MessageModule } from '../message/message.module'; import { TypeOrmModule } from '@nestjs/typeorm'; import { SnowballEntity } from './entity/snowball.entity'; +import { MessageEntity } from '../message/entity/message.entity'; +import { SnowballDecorationEntity } from './entity/snowball-decoration.entity'; @Module({ - imports: [TypeOrmModule.forFeature([SnowballEntity]), MessageModule], + imports: [ + TypeOrmModule.forFeature([ + SnowballEntity, + MessageEntity, + SnowballDecorationEntity + ]), + MessageModule + ], controllers: [SnowballController], providers: [SnowballService] }) diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 91b0b4c..9521444 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -1,23 +1,137 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, NotFoundException } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { SnowballEntity } from './entity/snowball.entity'; import { ReqCreateSnowballDto } from './dto/request/req-create-snowball.dto'; import { ReqUpdateSnowballDto } from './dto/request/req-update-snowball.dto'; +import { MessageEntity } from '../message/entity/message.entity'; +import { SnowballDto } from './dto/snowball.dto'; +import { SnowballDecorationEntity } from './entity/snowball-decoration.entity'; +import { DecorationSnowballDto } from './dto/decoration-snowball.dto'; +import { ResUpdateSnowballDecoDto } from './dto/response/res-update-decoration.dto'; +import { ReqUpdateSnowballDecoDto } from './dto/request/req-update-decoration.dto'; +import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; @Injectable() export class SnowballService { constructor( @InjectRepository(SnowballEntity) - private readonly snowballRepository: Repository + private readonly snowballRepository: Repository, + @InjectRepository(MessageEntity) + private readonly messageRepository: Repository, + @InjectRepository(SnowballDecorationEntity) + private readonly decorationRepository: Repository ) {} + async createSnowball( createSnowballDto: ReqCreateSnowballDto ): Promise { - const snowball = this.snowballRepository.create(createSnowballDto); - return await this.snowballRepository.save(snowball); + const snowball = this.snowballRepository.create({ + user_id: createSnowballDto.user_id, + title: createSnowballDto.title, + message_private: createSnowballDto.message_private ? new Date() : null + }); + const savedSnowball = await this.snowballRepository.save(snowball); + + // Create and save decorations + const decoList = createSnowballDto.deco_list; + for (const deco of decoList) { + await this.createDecoration(savedSnowball.id, deco); + } + + return savedSnowball; + } + + async createDecoration( + snowball_id: number, + deco: DecorationSnowballDto + ): Promise { + const decoration = this.decorationRepository.create({ + ...deco, + snowball_id + }); + const savedDecoration = await this.decorationRepository.save(decoration); + return savedDecoration; + } + + async updateSnowballDeco( + updateSnowballDecoDto: ReqUpdateSnowballDecoDto + ): Promise { + const { snowball_id, deco_list } = updateSnowballDecoDto; + + // Delete all decorations + await this.decorationRepository.delete({ + snowball_id + }); + + // Create new decorations + for (const deco of deco_list) { + await this.createDecoration(snowball_id, deco); + } + + // Return the updated snowball + const resSnowball: ResUpdateSnowballDecoDto = { + snowball_id, + deco_list + }; + return resSnowball; } - async updateSnowball(updateSnowballDto: ReqUpdateSnowballDto): Promise { - await this.snowballRepository.delete(updateSnowballDto.snowball_id); + + async updateSnowball( + updateSnowballDto: ReqUpdateSnowballDto + ): Promise { + const { snowball_id, title, message_private } = updateSnowballDto; + + // Update snowball if it exists + const snowball = await this.snowballRepository.findOne({ + where: { id: snowball_id } + }); + + if (snowball) { + snowball.title = title; + snowball.message_private = message_private ? new Date() : null; + await this.snowballRepository.save(snowball); + } else { + throw new NotFoundException('업데이트할 스노우볼이 존재하지 않습니다.'); + } + + // Return the updated snowball + const resSnowball: ResUpdateSnowballDto = { + snowball_id, + title, + message_private + }; + + return resSnowball; + } + + async getMessages(snowball_id: number): Promise { + const snowball = await this.snowballRepository.findOne({ + where: { id: snowball_id }, + relations: { + message_snowballs: true, + deco_snowballs: true + } + }); + + const resSnowball: SnowballDto = { + id: snowball.id, + uuid: snowball.snowball_uuid, + title: snowball.title, + message_private: snowball.message_private ? true : false, + deco_list: snowball.deco_snowballs, + message_list: snowball.message_snowballs.map(message => ({ + id: message.id, + decoration_id: message.decoration_id, + decoration_color: message.decoration_color, + content: message.content, + sender: message.sender, + opened: message.opened, + created: message.created_at + // letter_id: message.letter_id + })) + }; + + return resSnowball; } } From 8d70078cb06948990c86362eec49723a93dcd582 Mon Sep 17 00:00:00 2001 From: peageon Date: Mon, 20 Nov 2023 18:47:14 +0900 Subject: [PATCH 056/185] =?UTF-8?q?fix:=20=EC=8A=A4=EB=85=B8=EC=9A=B0?= =?UTF-8?q?=EB=B3=BC=20=EB=8D=B0=EC=9D=B4=ED=84=B0=EB=B2=A0=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=EC=97=90=20insert=EC=8B=9C=20@BeforeInsert=EB=A1=9C?= =?UTF-8?q?=20uuid=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/snowball/entity/snowball.entity.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index 6e6a64d..3b88aa7 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -7,7 +7,8 @@ import { CreateDateColumn, ManyToOne, OneToMany, - JoinColumn + JoinColumn, + BeforeInsert } from 'typeorm'; import { UserEntity } from './user.entity'; import { SnowballDecorationEntity } from './snowball-decoration.entity'; @@ -47,7 +48,8 @@ export class SnowballEntity { ) deco_snowballs: SnowballDecorationEntity[]; - beforeInsert() { + @BeforeInsert() + generateSnowballUUID() { this.snowball_uuid = uuidv4(); } } From 616eb305d3b04325bd02089fc57ff55515801116 Mon Sep 17 00:00:00 2001 From: peageon Date: Mon, 20 Nov 2023 20:18:10 +0900 Subject: [PATCH 057/185] =?UTF-8?q?fix:=20PUT=20/snowball/decoration=20?= =?UTF-8?q?=EB=9D=BC=EC=9A=B0=ED=8C=85=20=EA=B3=A0=EC=B9=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/snowball/snowball.controller.ts | 2 +- back/src/modules/snowball/snowball.service.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index 0b1734d..8ae387b 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -34,7 +34,7 @@ export class SnowballController { return snowball; } - @Put() + @Put('/decoration') @ApiResponse({ status: 200, description: '스노우볼 데코레이션 업데이트 성공', diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 9521444..9d5254f 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -113,6 +113,7 @@ export class SnowballService { deco_snowballs: true } }); + console.log(snowball.message_snowballs); const resSnowball: SnowballDto = { id: snowball.id, From dab2a7a790921ed9c484aaa99c83eb675e28f768 Mon Sep 17 00:00:00 2001 From: peageon Date: Mon, 20 Nov 2023 20:34:55 +0900 Subject: [PATCH 058/185] =?UTF-8?q?fix:=20ResUpdateSnowballDto=20id=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=ED=95=98=EA=B2=8C=20=EB=AA=85=EC=84=B8=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../snowball/dto/response/res-update-snowball.dto.ts | 10 +++------- back/src/modules/snowball/snowball.service.ts | 6 +++++- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/back/src/modules/snowball/dto/response/res-update-snowball.dto.ts b/back/src/modules/snowball/dto/response/res-update-snowball.dto.ts index 00dec74..d5decdd 100644 --- a/back/src/modules/snowball/dto/response/res-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/response/res-update-snowball.dto.ts @@ -1,13 +1,9 @@ -import { IsString, IsUUID, IsBoolean } from '@nestjs/class-validator'; +import { IsString, IsBoolean, IsNumber } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class ResUpdateSnowballDto { - @IsUUID() - @ApiProperty({ - type: String, - description: '변경된 스노우볼의 uuid', - format: 'uuid' - }) + @IsNumber() + @ApiProperty({ type: Number, description: '스노우볼 id' }) readonly snowball_id: number; @IsString() diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 9d5254f..f31587c 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -106,13 +106,17 @@ export class SnowballService { } async getMessages(snowball_id: number): Promise { - const snowball = await this.snowballRepository.findOne({ + const snowballs = await this.snowballRepository.find({ where: { id: snowball_id }, relations: { message_snowballs: true, deco_snowballs: true } }); + if (!snowballs) { + throw new NotFoundException('스노우볼이 존재하지 않습니다.'); + } + const snowball = snowballs[0]; console.log(snowball.message_snowballs); const resSnowball: SnowballDto = { From 9fe93375a49b62893715e9d6ed0dbcd15d6a1562 Mon Sep 17 00:00:00 2001 From: peageon Date: Mon, 20 Nov 2023 23:45:00 +0900 Subject: [PATCH 059/185] =?UTF-8?q?fix:=20GET=20/snowball/:snowball=5Fid/m?= =?UTF-8?q?essages=20=EA=B3=A0=EC=B9=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/entity/message.entity.ts | 4 ++-- .../src/modules/snowball/entity/snowball-decoration.entity.ts | 4 ++-- back/src/modules/snowball/entity/snowball.entity.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index e54f137..8e86b56 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -34,7 +34,7 @@ export class MessageEntity { @CreateDateColumn() created_at: Date; - @ManyToOne(() => SnowballEntity, message => message.message_snowballs) + @ManyToOne(() => SnowballEntity, snowball => snowball.message_snowballs) @JoinColumn({ name: 'snowball_id' }) - message_snowballs: SnowballEntity; + snowball: SnowballEntity; } diff --git a/back/src/modules/snowball/entity/snowball-decoration.entity.ts b/back/src/modules/snowball/entity/snowball-decoration.entity.ts index d779663..cfd2c16 100644 --- a/back/src/modules/snowball/entity/snowball-decoration.entity.ts +++ b/back/src/modules/snowball/entity/snowball-decoration.entity.ts @@ -24,7 +24,7 @@ export class SnowballDecorationEntity { @Column() location: number; - @ManyToOne(() => SnowballEntity, deco => deco.deco_snowballs) + @ManyToOne(() => SnowballEntity, snowball => snowball.deco_snowballs) @JoinColumn({ name: 'snowball_id' }) - deco_snowballs: SnowballEntity; + snowball: SnowballEntity; } diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index 3b88aa7..32f5497 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -39,12 +39,12 @@ export class SnowballEntity { @JoinColumn({ name: 'user_id' }) user: UserEntity; - @OneToMany(() => MessageEntity, message => message.snowball_id) + @OneToMany(() => MessageEntity, message => message.snowball) message_snowballs: MessageEntity[]; @OneToMany( () => SnowballDecorationEntity, - snowball_deco => snowball_deco.snowball_id + snowball_deco => snowball_deco.snowball ) deco_snowballs: SnowballDecorationEntity[]; From e49eb142a0a9ba3475f1097a904e8aa8f11e92a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 21 Nov 2023 02:18:59 +0900 Subject: [PATCH 060/185] =?UTF-8?q?fix:=20create=EC=8B=9C=20dto=EB=B0=98?= =?UTF-8?q?=ED=99=98=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/snowball/snowball.controller.ts | 4 +++- back/src/modules/snowball/snowball.service.ts | 24 ++++++++++++++----- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index 8ae387b..1172550 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -29,7 +29,9 @@ export class SnowballController { type: SnowballDto }) @ApiBody({ type: ReqCreateSnowballDto }) - createSnowball(@Body() createSnowballDto: ReqCreateSnowballDto) { + createSnowball( + @Body() createSnowballDto: ReqCreateSnowballDto + ): Promise { const snowball = this.snowballService.createSnowball(createSnowballDto); return snowball; } diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index f31587c..399ad1b 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -25,7 +25,7 @@ export class SnowballService { async createSnowball( createSnowballDto: ReqCreateSnowballDto - ): Promise { + ): Promise { const snowball = this.snowballRepository.create({ user_id: createSnowballDto.user_id, title: createSnowballDto.title, @@ -33,25 +33,37 @@ export class SnowballService { }); const savedSnowball = await this.snowballRepository.save(snowball); - // Create and save decorations + // To Do: bulk insert로 변경 & 반환값으로 Dto 생성하기 const decoList = createSnowballDto.deco_list; for (const deco of decoList) { await this.createDecoration(savedSnowball.id, deco); } - - return savedSnowball; + const combinedSnowballDto: SnowballDto = { + id: savedSnowball.id, + uuid: savedSnowball.snowball_uuid, + title: savedSnowball.title, + message_private: savedSnowball.message_private === null ? false : true, + deco_list: decoList, + message_list: [] + }; + return combinedSnowballDto; } async createDecoration( snowball_id: number, deco: DecorationSnowballDto - ): Promise { + ): Promise { const decoration = this.decorationRepository.create({ ...deco, snowball_id }); const savedDecoration = await this.decorationRepository.save(decoration); - return savedDecoration; + const decorationDto: DecorationSnowballDto = { + decoration_id: savedDecoration.decoration_id, + decoration_color: savedDecoration.decoration_color, + location: savedDecoration.location + }; + return decorationDto; } async updateSnowballDeco( From a2570cdd01436d2fbbcbb46b23cac47319e7706c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 21 Nov 2023 02:58:23 +0900 Subject: [PATCH 061/185] =?UTF-8?q?feat:=20update=20snowball=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=20=EC=B5=9C=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/snowball/snowball.service.ts | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 399ad1b..6a65d77 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -33,7 +33,7 @@ export class SnowballService { }); const savedSnowball = await this.snowballRepository.save(snowball); - // To Do: bulk insert로 변경 & 반환값으로 Dto 생성하기 + // To Do: bulk insert로 변경 & 반환값으로 Dto const decoList = createSnowballDto.deco_list; for (const deco of decoList) { await this.createDecoration(savedSnowball.id, deco); @@ -94,27 +94,28 @@ export class SnowballService { ): Promise { const { snowball_id, title, message_private } = updateSnowballDto; - // Update snowball if it exists - const snowball = await this.snowballRepository.findOne({ - where: { id: snowball_id } - }); - - if (snowball) { - snowball.title = title; - snowball.message_private = message_private ? new Date() : null; - await this.snowballRepository.save(snowball); - } else { + const updateResult = await this.snowballRepository + .createQueryBuilder() + .update(SnowballEntity) + .set({ + title, + message_private: message_private ? new Date() : null + }) + .where('id = :id', { id: snowball_id }) + .execute(); + console.log(updateResult); + if (!updateResult.affected) { throw new NotFoundException('업데이트할 스노우볼이 존재하지 않습니다.'); } // Return the updated snowball - const resSnowball: ResUpdateSnowballDto = { + const resUpdateSnowballDto: ResUpdateSnowballDto = { snowball_id, title, message_private }; - return resSnowball; + return resUpdateSnowballDto; } async getMessages(snowball_id: number): Promise { From d2791eed391e2fb9f2f37673f2fd451605392083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 21 Nov 2023 04:00:33 +0900 Subject: [PATCH 062/185] =?UTF-8?q?fix:=20api=EB=84=A4=EC=9D=B4=EB=B0=8D?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20&=20letter=5Fid=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/req-create-message.dto.ts | 5 +++++ .../src/modules/message/entity/message.entity.ts | 5 ++++- back/src/modules/message/message.service.ts | 3 ++- .../entity/snowball-decoration.entity.ts | 2 +- .../modules/snowball/entity/snowball.entity.ts | 9 +++------ back/src/modules/snowball/entity/user.entity.ts | 2 +- back/src/modules/snowball/snowball.controller.ts | 10 +++++----- back/src/modules/snowball/snowball.service.ts | 16 ++++++++-------- 8 files changed, 29 insertions(+), 23 deletions(-) diff --git a/back/src/modules/message/dto/request/req-create-message.dto.ts b/back/src/modules/message/dto/request/req-create-message.dto.ts index 94f3427..175a900 100644 --- a/back/src/modules/message/dto/request/req-create-message.dto.ts +++ b/back/src/modules/message/dto/request/req-create-message.dto.ts @@ -26,4 +26,9 @@ export class ReqCreateMessageDto { @IsNotEmpty() @ApiProperty({ type: String, description: '장식 색상', example: '#FFFFFF' }) readonly decoration_color: string; + + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '편지지 종류' }) + readonly letter_id: number; } diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 8e86b56..e33721d 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -22,6 +22,9 @@ export class MessageEntity { @Column({ length: 7 }) decoration_color: string; + @Column() + letter_id: number; + @Column({ type: 'text' }) content: string; @@ -34,7 +37,7 @@ export class MessageEntity { @CreateDateColumn() created_at: Date; - @ManyToOne(() => SnowballEntity, snowball => snowball.message_snowballs) + @ManyToOne(() => SnowballEntity, snowball => snowball.messages) @JoinColumn({ name: 'snowball_id' }) snowball: SnowballEntity; } diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 8b197fd..4a4386c 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -20,7 +20,8 @@ export class MessageService { sender: createMessageDto.sender, content: createMessageDto.content, decoration_id: createMessageDto.decoration_id, - decoration_color: createMessageDto.decoration_color + decoration_color: createMessageDto.decoration_color, + letter_id: createMessageDto.letter_id // opened와 created_at은 자동으로 설정 }); const savedMessage = await this.messageRepository.save(messageEntity); diff --git a/back/src/modules/snowball/entity/snowball-decoration.entity.ts b/back/src/modules/snowball/entity/snowball-decoration.entity.ts index cfd2c16..9b25028 100644 --- a/back/src/modules/snowball/entity/snowball-decoration.entity.ts +++ b/back/src/modules/snowball/entity/snowball-decoration.entity.ts @@ -24,7 +24,7 @@ export class SnowballDecorationEntity { @Column() location: number; - @ManyToOne(() => SnowballEntity, snowball => snowball.deco_snowballs) + @ManyToOne(() => SnowballEntity, snowball => snowball.decorations) @JoinColumn({ name: 'snowball_id' }) snowball: SnowballEntity; } diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index 32f5497..9652f7a 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -40,13 +40,10 @@ export class SnowballEntity { user: UserEntity; @OneToMany(() => MessageEntity, message => message.snowball) - message_snowballs: MessageEntity[]; + messages: MessageEntity[]; - @OneToMany( - () => SnowballDecorationEntity, - snowball_deco => snowball_deco.snowball - ) - deco_snowballs: SnowballDecorationEntity[]; + @OneToMany(() => SnowballDecorationEntity, decoration => decoration.snowball) + decorations: SnowballDecorationEntity[]; @BeforeInsert() generateSnowballUUID() { diff --git a/back/src/modules/snowball/entity/user.entity.ts b/back/src/modules/snowball/entity/user.entity.ts index b397bd7..31e64bc 100644 --- a/back/src/modules/snowball/entity/user.entity.ts +++ b/back/src/modules/snowball/entity/user.entity.ts @@ -24,6 +24,6 @@ export class UserEntity { @CreateDateColumn() created_at: Date; - @OneToMany(() => SnowballEntity, snowball => snowball.user_id) + @OneToMany(() => SnowballEntity, snowball => snowball.user) snowballs: SnowballEntity[]; } diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index 1172550..fbc7f6f 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -70,18 +70,18 @@ export class SnowballController { return snowball; } - @Get('/:snowball_id/messages') + @Get('/:snowball_id/info') @ApiResponse({ status: 200, - description: '스노우볼 메시지들 조회 성공', + description: '스노우볼 조회 성공', type: SnowballDto }) @ApiOperation({ - summary: '스노우볼 메시지들 조회 API', - description: '스노우볼에 속한 메시지들을 조회합니다.' + summary: '스노우볼 조회 API', + description: '스노우볼의 정보를 조회합니다.' }) async getMessages(@Param('snowball_id') snowball_id: number) { - const messages = await this.snowballService.getMessages(snowball_id); + const messages = await this.snowballService.getSnowball(snowball_id); return messages; } } diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 6a65d77..8cdc0bb 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -118,35 +118,35 @@ export class SnowballService { return resUpdateSnowballDto; } - async getMessages(snowball_id: number): Promise { + async getSnowball(snowball_id: number): Promise { const snowballs = await this.snowballRepository.find({ where: { id: snowball_id }, relations: { - message_snowballs: true, - deco_snowballs: true + messages: true, + decorations: true } }); if (!snowballs) { throw new NotFoundException('스노우볼이 존재하지 않습니다.'); } const snowball = snowballs[0]; - console.log(snowball.message_snowballs); + console.log(snowball); const resSnowball: SnowballDto = { id: snowball.id, uuid: snowball.snowball_uuid, title: snowball.title, message_private: snowball.message_private ? true : false, - deco_list: snowball.deco_snowballs, - message_list: snowball.message_snowballs.map(message => ({ + deco_list: snowball.decorations, + message_list: snowball.messages.map(message => ({ id: message.id, decoration_id: message.decoration_id, decoration_color: message.decoration_color, content: message.content, sender: message.sender, opened: message.opened, - created: message.created_at - // letter_id: message.letter_id + created: message.created_at, + letter_id: message.letter_id })) }; From bee4a0d456de39a75f9a100810a57dcca7e29501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 21 Nov 2023 04:04:14 +0900 Subject: [PATCH 063/185] =?UTF-8?q?feat:=20=EC=83=81=ED=83=9C=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=A7=80=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/snowball/snowball.controller.ts | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index fbc7f6f..8dabbea 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -1,4 +1,12 @@ -import { Controller, Post, Put, Body, Param, Get } from '@nestjs/common'; +import { + Controller, + Post, + Put, + Body, + Param, + Get, + HttpCode +} from '@nestjs/common'; import { SnowballService } from './snowball.service'; import { ApiBody, @@ -20,6 +28,7 @@ export class SnowballController { constructor(private readonly snowballService: SnowballService) {} @Post() + @HttpCode(201) @ApiOperation({ summary: '스노우볼 생성 API', description: '스노우볼을 생성합니다.' @@ -37,6 +46,7 @@ export class SnowballController { } @Put('/decoration') + @HttpCode(200) @ApiResponse({ status: 200, description: '스노우볼 데코레이션 업데이트 성공', @@ -55,6 +65,7 @@ export class SnowballController { } @Put() + @HttpCode(200) @ApiResponse({ status: 200, description: '스노우볼 업데이트 성공', @@ -71,6 +82,7 @@ export class SnowballController { } @Get('/:snowball_id/info') + @HttpCode(200) @ApiResponse({ status: 200, description: '스노우볼 조회 성공', @@ -80,8 +92,8 @@ export class SnowballController { summary: '스노우볼 조회 API', description: '스노우볼의 정보를 조회합니다.' }) - async getMessages(@Param('snowball_id') snowball_id: number) { - const messages = await this.snowballService.getSnowball(snowball_id); - return messages; + async getSnowball(@Param('snowball_id') snowball_id: number) { + const snowball = await this.snowballService.getSnowball(snowball_id); + return snowball; } } From e233ba44747fee6262828fe75fa5a9c1affa2de9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 21 Nov 2023 04:37:55 +0900 Subject: [PATCH 064/185] =?UTF-8?q?feat:=20getAllMessages=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.service.ts | 2 + back/src/modules/message/dto/message.dto.ts | 4 ++ .../modules/message/entity/message.entity.ts | 2 +- .../src/modules/message/message.controller.ts | 23 ++++++++ back/src/modules/message/message.module.ts | 7 ++- back/src/modules/message/message.service.ts | 52 +++++++++++++++++-- back/src/modules/snowball/snowball.service.ts | 11 ++-- 7 files changed, 86 insertions(+), 15 deletions(-) diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index 26b119e..0f93e57 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -44,6 +44,7 @@ export class AuthService { id: 1, decoration_id: 15, decoration_color: '#FFFFFF', + letter_id: 1, content: '편지 내용', sender: '널 좋아하는 사람', opened: null, @@ -53,6 +54,7 @@ export class AuthService { id: 2, decoration_id: 15, decoration_color: '#FFFFFF', + letter_id: 1, content: '편지 내용', sender: '찬우를 사랑하는 사람', opened: null, diff --git a/back/src/modules/message/dto/message.dto.ts b/back/src/modules/message/dto/message.dto.ts index 5df472b..46228a8 100644 --- a/back/src/modules/message/dto/message.dto.ts +++ b/back/src/modules/message/dto/message.dto.ts @@ -14,6 +14,10 @@ export class MessageDto { @ApiProperty({ type: String, description: '데코레이션 색상' }) readonly decoration_color: string; + @IsNumber() + @ApiProperty({ type: Number, description: '편지지 종류' }) + readonly letter_id: number; + @IsString() @ApiProperty({ type: String, description: '메시지 내용' }) readonly content: string; diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index e33721d..62a9f27 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -35,7 +35,7 @@ export class MessageEntity { opened: Date | null; @CreateDateColumn() - created_at: Date; + created: Date; @ManyToOne(() => SnowballEntity, snowball => snowball.messages) @JoinColumn({ name: 'snowball_id' }) diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 59d0236..75e1fac 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -1,6 +1,7 @@ import { Controller, Post, + Get, Delete, Body, Param, @@ -11,6 +12,7 @@ import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; import { ReqDeleteMessageDto } from './dto/request/req-delete-message.dto'; import { ApiBody, ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; +import { MessageDto } from './dto/message.dto'; @ApiTags('Message API') @Controller('message') @@ -55,4 +57,25 @@ export class MessageController { async deleteMessage(@Param() deleteMessageDto: ReqDeleteMessageDto) { await this.messageService.deleteMessage(deleteMessageDto); } + + @Get() + @HttpCode(200) + @ApiOperation({ + summary: '메세지 조회 API', + description: '모든 메세지를 조회합니다' + }) + @ApiResponse({ + status: 200, + type: MessageDto + }) + @ApiResponse({ + status: 500, + description: 'Find Fail' + }) + async getAllMessages( + @Param('user_id') user_id: number + ): Promise { + const messages = await this.messageService.getAllMessages(user_id); + return messages; + } } diff --git a/back/src/modules/message/message.module.ts b/back/src/modules/message/message.module.ts index f850ab2..1618e70 100644 --- a/back/src/modules/message/message.module.ts +++ b/back/src/modules/message/message.module.ts @@ -3,9 +3,12 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { MessageController } from './message.controller'; import { MessageService } from './message.service'; import { MessageEntity } from './entity/message.entity'; - +import { UserEntity } from '../snowball/entity/user.entity'; +import { SnowballEntity } from '../snowball/entity/snowball.entity'; @Module({ - imports: [TypeOrmModule.forFeature([MessageEntity])], + imports: [ + TypeOrmModule.forFeature([UserEntity, SnowballEntity, MessageEntity]) + ], controllers: [MessageController], providers: [MessageService] }) diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 4a4386c..44bff30 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -1,14 +1,21 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, NotFoundException } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; import { ReqDeleteMessageDto } from './dto/request/req-delete-message.dto'; import { MessageEntity } from './entity/message.entity'; +import { UserEntity } from '../snowball/entity/user.entity'; +import { SnowballEntity } from '../snowball/entity/snowball.entity'; import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; +import { MessageDto } from './dto/message.dto'; @Injectable() export class MessageService { constructor( + @InjectRepository(UserEntity) + private readonly userRepository: Repository, + @InjectRepository(SnowballEntity) + private readonly snowballRepository: Repository, @InjectRepository(MessageEntity) private readonly messageRepository: Repository ) {} @@ -22,7 +29,7 @@ export class MessageService { decoration_id: createMessageDto.decoration_id, decoration_color: createMessageDto.decoration_color, letter_id: createMessageDto.letter_id - // opened와 created_at은 자동으로 설정 + // opened와 created는 자동으로 설정 }); const savedMessage = await this.messageRepository.save(messageEntity); @@ -38,7 +45,44 @@ export class MessageService { await this.messageRepository.delete(deleteMessageDto.message_id); } - async findAllMessage(): Promise { - return await this.messageRepository.find(); + async getAllMessages(user_id: number): Promise { + const user = await this.userRepository.findOne({ + where: { id: user_id }, + relations: { + snowballs: { + messages: true + } + } + }); + + if (!user) { + throw new NotFoundException(`User with id ${user_id} not found`); + } + const messages: MessageEntity[] = user.snowballs.flatMap( + snowball => snowball.messages + ); + const messagesDto: MessageDto[] = messages.map(message => { + const { + id, + decoration_id, + decoration_color, + letter_id, + content, + sender, + opened, + created + } = message; + return { + id, + decoration_id, + decoration_color, + letter_id, + content, + sender, + opened, + created + }; + }); + return messagesDto; } } diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 8cdc0bb..84e6098 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -4,7 +4,6 @@ import { Repository } from 'typeorm'; import { SnowballEntity } from './entity/snowball.entity'; import { ReqCreateSnowballDto } from './dto/request/req-create-snowball.dto'; import { ReqUpdateSnowballDto } from './dto/request/req-update-snowball.dto'; -import { MessageEntity } from '../message/entity/message.entity'; import { SnowballDto } from './dto/snowball.dto'; import { SnowballDecorationEntity } from './entity/snowball-decoration.entity'; import { DecorationSnowballDto } from './dto/decoration-snowball.dto'; @@ -17,8 +16,6 @@ export class SnowballService { constructor( @InjectRepository(SnowballEntity) private readonly snowballRepository: Repository, - @InjectRepository(MessageEntity) - private readonly messageRepository: Repository, @InjectRepository(SnowballDecorationEntity) private readonly decorationRepository: Repository ) {} @@ -119,18 +116,16 @@ export class SnowballService { } async getSnowball(snowball_id: number): Promise { - const snowballs = await this.snowballRepository.find({ + const snowball = await this.snowballRepository.findOne({ where: { id: snowball_id }, relations: { messages: true, decorations: true } }); - if (!snowballs) { + if (!snowball) { throw new NotFoundException('스노우볼이 존재하지 않습니다.'); } - const snowball = snowballs[0]; - console.log(snowball); const resSnowball: SnowballDto = { id: snowball.id, @@ -145,7 +140,7 @@ export class SnowballService { content: message.content, sender: message.sender, opened: message.opened, - created: message.created_at, + created: message.created, letter_id: message.letter_id })) }; From 190659c1560016923357a7d59b245c4b38931d40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 21 Nov 2023 05:04:50 +0900 Subject: [PATCH 065/185] =?UTF-8?q?feat:=20index=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.service.ts | 4 +--- back/src/modules/snowball/entity/snowball.entity.ts | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 44bff30..3c165e9 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -5,7 +5,6 @@ import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; import { ReqDeleteMessageDto } from './dto/request/req-delete-message.dto'; import { MessageEntity } from './entity/message.entity'; import { UserEntity } from '../snowball/entity/user.entity'; -import { SnowballEntity } from '../snowball/entity/snowball.entity'; import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; import { MessageDto } from './dto/message.dto'; @@ -14,8 +13,6 @@ export class MessageService { constructor( @InjectRepository(UserEntity) private readonly userRepository: Repository, - @InjectRepository(SnowballEntity) - private readonly snowballRepository: Repository, @InjectRepository(MessageEntity) private readonly messageRepository: Repository ) {} @@ -46,6 +43,7 @@ export class MessageService { } async getAllMessages(user_id: number): Promise { + //To Do: query builder로 개선하기 const user = await this.userRepository.findOne({ where: { id: user_id }, relations: { diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index 9652f7a..be05c67 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -3,6 +3,7 @@ import { v4 as uuidv4 } from 'uuid'; import { Entity, Column, + Index, PrimaryGeneratedColumn, CreateDateColumn, ManyToOne, @@ -15,6 +16,7 @@ import { SnowballDecorationEntity } from './snowball-decoration.entity'; import { MessageEntity } from '../../message/entity/message.entity'; @Entity({ name: 'snowball' }) +@Index('idx_snowball', ['snowball_uuid'], { unique: true }) export class SnowballEntity { @PrimaryGeneratedColumn() id: number; From f7a70f9f5a9422f69cde4f4852ba622fd49b53e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 21 Nov 2023 07:20:44 +0900 Subject: [PATCH 066/185] =?UTF-8?q?fix:=20message=20get=20=ED=8C=8C?= =?UTF-8?q?=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EC=95=88=EB=B0=9B=EB=8D=98=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 75e1fac..5bd9157 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -58,7 +58,7 @@ export class MessageController { await this.messageService.deleteMessage(deleteMessageDto); } - @Get() + @Get('/:user_id') @HttpCode(200) @ApiOperation({ summary: '메세지 조회 API', From 09474b030204452d902a13c7c86b85d5e619e7bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 21 Nov 2023 07:26:24 +0900 Subject: [PATCH 067/185] =?UTF-8?q?fix:=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.controller.ts | 2 +- back/src/modules/snowball/snowball.controller.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 5bd9157..bb7886f 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -58,7 +58,7 @@ export class MessageController { await this.messageService.deleteMessage(deleteMessageDto); } - @Get('/:user_id') + @Get('/:user_id/messages') @HttpCode(200) @ApiOperation({ summary: '메세지 조회 API', diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index 8dabbea..bf14346 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -81,7 +81,7 @@ export class SnowballController { return snowball; } - @Get('/:snowball_id/info') + @Get('/info/:snowball_id') @HttpCode(200) @ApiResponse({ status: 200, From 06e8d94d560b71eb3ca34cfaa0635335ae0680ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jinsoo=20Choi=20=28=EC=B5=9C=EC=A7=84=EC=88=98=29?= Date: Tue, 21 Nov 2023 15:16:20 +0900 Subject: [PATCH 068/185] =?UTF-8?q?feat:=20=EB=B0=B1=EC=97=94=EB=93=9C=20?= =?UTF-8?q?=EC=9B=8C=ED=81=AC=ED=94=8C=EB=A1=9C=EC=9A=B0=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/backend.yml | 85 +++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 .github/workflows/backend.yml diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml new file mode 100644 index 0000000..805c3bb --- /dev/null +++ b/.github/workflows/backend.yml @@ -0,0 +1,85 @@ +# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs + +name: Node.js CI + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + # test: + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + + # - name: Use Node.js 20.5.1 + # uses: actions/setup-node@v4 + # with: + # node-version: 20.5.1 + + # - name: Install package + # run: npm install + # working-directory: ./was + + # - name: npm build + # run: npm run build --if-present + # working-directory: ./was + + # - name: npm test + # run: npm test + # working-directory: ./was + build_docker: + needs: test + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + context: ./was + push: true + tags: ghcr.io/yunuo46/was_test:latest + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GHCR_TOKEN }} + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: ./was + push: true + tags: ghcr.io/yunuo46/was_test:latest + deploy_docker: + needs: build_docker + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: SSH Version Check + run: ssh -V + + - name: Deploy to Server via SSH + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.SERVER_HOST }} + username: ${{ secrets.SERVER_USERNAME }} + password: ${{ secrets.SERVER_PASSWORD }} + port: 22 + script: | + ssh -i ~/.ssh/id_rsa root@10.0.2.6 << 'EOF' + echo ${{ secrets.GHCR_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin + docker pull ghcr.io/yunuo46/was_test:latest + docker stop was_test || true + docker rm was_test || true + docker run -d --name was_test -p 3000:3000 ghcr.io/yunuo46/was_test:latest From 08fb86b03b78f7c92656db92e4ece3b889eadaab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 21 Nov 2023 20:30:31 +0900 Subject: [PATCH 069/185] =?UTF-8?q?fix:=20=EA=B0=95=EC=A0=9C=20push=20?= =?UTF-8?q?=ED=9B=84=20=EB=B3=80=EA=B2=BD=20=EC=82=AC=ED=95=AD=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/BackEnd.yml | 86 +++++++++++++++++++ back/.dockerfile | 7 ++ back/Dockerfile | 12 +++ .../src/modules/message/message.controller.ts | 2 +- 4 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/BackEnd.yml create mode 100644 back/.dockerfile create mode 100644 back/Dockerfile diff --git a/.github/workflows/BackEnd.yml b/.github/workflows/BackEnd.yml new file mode 100644 index 0000000..e4f1783 --- /dev/null +++ b/.github/workflows/BackEnd.yml @@ -0,0 +1,86 @@ +# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs + +name: Node.js CI + +on: + push: + branches: ["BE/main"] + pull_request: + branches: ["BE/main"] + +jobs: + # test: + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + + # - name: Use Node.js 20.5.1 + # uses: actions/setup-node@v4 + # with: + # node-version: 20.5.1 + + # - name: Install package + # run: npm install + # working-directory: ./back + + # - name: npm build + # run: npm run build --if-present + # working-directory: ./back + + # - name: npm test + # run: npm test + # working-directory: ./back + build_docker: + # needs: test + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + context: ./back + push: true + tags: ghcr.io/yunuo46/was_test:latest + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: yunuo46 + password: ${{ secrets.GHCR_TOKEN }} + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: ./back + push: true + tags: ghcr.io/yunuo46/was_test:latest + deploy_docker: + needs: build_docker + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: SSH Version Check + run: ssh -V + + - name: Deploy to Server via SSH + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.SERVER_HOST }} + username: ${{ secrets.SERVER_USERNAME }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + port: 22 + script: | + ssh -i ~/.ssh/id_rsa root@10.0.2.6 << 'EOF' + echo "${{ secrets.ENV_FILE }}" > .env + echo ${{ secrets.GHCR_TOKEN }} | docker login ghcr.io -u yunuo46 --password-stdin + docker pull ghcr.io/yunuo46/was_test:latest + docker stop was_test || true + docker rm was_test || true + docker run -d --name was_test -p 3000:3000 --env-file .env ghcr.io/yunuo46/was_test:latest diff --git a/back/.dockerfile b/back/.dockerfile new file mode 100644 index 0000000..76f3633 --- /dev/null +++ b/back/.dockerfile @@ -0,0 +1,7 @@ +node_modules/ +dist/ + +.git +.gitingore +.dockerignore +Dockerfile \ No newline at end of file diff --git a/back/Dockerfile b/back/Dockerfile new file mode 100644 index 0000000..c759ec8 --- /dev/null +++ b/back/Dockerfile @@ -0,0 +1,12 @@ +FROM node:20-alpine + +RUN mkdir -p /app +WORKDIR /app + +ADD . /app/ + +RUN npm install + +EXPOSE 3000 + +ENTRYPOINT npm start \ No newline at end of file diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index bb7886f..61d2480 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -58,7 +58,7 @@ export class MessageController { await this.messageService.deleteMessage(deleteMessageDto); } - @Get('/:user_id/messages') + @Get('all/:user_id/') @HttpCode(200) @ApiOperation({ summary: '메세지 조회 API', From 6e3e7d8b911d635a65e012bab636feb4bca2f083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 21 Nov 2023 23:34:17 +0900 Subject: [PATCH 070/185] =?UTF-8?q?feat:=20swagger=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=ED=8C=9D=EC=97=85=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/FrontEnd.yml | 8 +++--- back/package-lock.json | 48 ++++++++++++++++++++++++++++++++++ back/package.json | 1 + back/src/main.ts | 11 ++++++++ back/src/util/swagger.ts | 26 +++++++++++++++++- back/tsconfig.json | 3 +-- 6 files changed, 90 insertions(+), 7 deletions(-) diff --git a/.github/workflows/FrontEnd.yml b/.github/workflows/FrontEnd.yml index 012a66e..c1a6c1b 100644 --- a/.github/workflows/FrontEnd.yml +++ b/.github/workflows/FrontEnd.yml @@ -5,7 +5,7 @@ name: FrontEnd deploy # Controls when the workflow will run on: push: - branches: [ "FE/main" ] + branches: ["FE/main"] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -21,8 +21,8 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v2 with: - node-version: '18' - + node-version: "18" + - name: Check Node v run: node -v @@ -41,7 +41,7 @@ jobs: run: | aws s3 sync ./front/dist s3://snowball-ssock --region ap-northeast-2 --delete - # 업로드한 s3 파일을 각 CDN 캐시 무효화하여 리프레시 하기 + # 업로드한 s3 파일을 각 CDN 캐시 무효화하여 리프레시 하기 - name: CloudFront Invalidation env: CLOUD_FRONT_ID: ${{ secrets.AWS_CLOUDFRONT_ID}} diff --git a/back/package-lock.json b/back/package-lock.json index b5f3b04..d11dab3 100644 --- a/back/package-lock.json +++ b/back/package-lock.json @@ -19,6 +19,7 @@ "@nestjs/typeorm": "^10.0.0", "class-validator": "^0.14.0", "dotenv": "^16.3.1", + "express-basic-auth": "^1.2.1", "mysql2": "^3.6.3", "passport": "^0.6.0", "passport-facebook": "^3.0.0", @@ -3190,6 +3191,22 @@ "node": ">=6.0.0" } }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/big-integer": { "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", @@ -4934,6 +4951,14 @@ "node": ">= 0.10.0" } }, + "node_modules/express-basic-auth": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/express-basic-auth/-/express-basic-auth-1.2.1.tgz", + "integrity": "sha512-L6YQ1wQ/mNjVLAmK3AG1RK6VkokA1BIY6wmiH304Xtt/cLTps40EusZsU1Uop+v9lTDPxdtzbFmdXfFO3KEnwA==", + "dependencies": { + "basic-auth": "^2.0.1" + } + }, "node_modules/express/node_modules/body-parser": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", @@ -13075,6 +13100,21 @@ "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "requires": { + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, "big-integer": { "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", @@ -14370,6 +14410,14 @@ } } }, + "express-basic-auth": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/express-basic-auth/-/express-basic-auth-1.2.1.tgz", + "integrity": "sha512-L6YQ1wQ/mNjVLAmK3AG1RK6VkokA1BIY6wmiH304Xtt/cLTps40EusZsU1Uop+v9lTDPxdtzbFmdXfFO3KEnwA==", + "requires": { + "basic-auth": "^2.0.1" + } + }, "external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", diff --git a/back/package.json b/back/package.json index 8c63dd9..baa6057 100644 --- a/back/package.json +++ b/back/package.json @@ -30,6 +30,7 @@ "@nestjs/typeorm": "^10.0.0", "class-validator": "^0.14.0", "dotenv": "^16.3.1", + "express-basic-auth": "^1.2.1", "mysql2": "^3.6.3", "passport": "^0.6.0", "passport-facebook": "^3.0.0", diff --git a/back/src/main.ts b/back/src/main.ts index deca767..cf8301a 100644 --- a/back/src/main.ts +++ b/back/src/main.ts @@ -1,9 +1,20 @@ import { NestFactory } from '@nestjs/core'; import { setupSwagger } from 'src/util/swagger'; import { AppModule } from './app.module'; +import * as expressBasicAuth from 'express-basic-auth'; async function bootstrap() { const app = await NestFactory.create(AppModule); + app.use( + //이 부분 추가 + ['/docs'], // docs(swagger end point)에 진입시 + expressBasicAuth({ + challenge: true, + users: { + [process.env.SWAGGER_USER]: process.env.SWAGGER_PASSWORD // 지정된 ID/비밀번호 + } + }) + ); setupSwagger(app); await app.listen(3000); } diff --git a/back/src/util/swagger.ts b/back/src/util/swagger.ts index 94b2fef..a9cd949 100644 --- a/back/src/util/swagger.ts +++ b/back/src/util/swagger.ts @@ -1,13 +1,37 @@ import { INestApplication } from '@nestjs/common'; import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; +import * as expressBasicAuth from 'express-basic-auth'; export function setupSwagger(app: INestApplication): void { + app.use( + ['/api'], + expressBasicAuth({ + challenge: true, + users: { + [process.env.SWAGGER_USER]: process.env.SWAGGER_PASSWORD + } + }) + ); const config = new DocumentBuilder() .setTitle('SSOCK API') .setDescription('The SSOCK API description') .setVersion('1.0') .addTag('ssock') + .addBearerAuth( + { + type: 'http', + scheme: 'bearer', + bearerFormat: 'JWT', + name: 'JWT', + in: 'header' + }, + 'token' + ) .build(); const document = SwaggerModule.createDocument(app, config); - SwaggerModule.setup('api', app, document); + SwaggerModule.setup('api', app, document, { + swaggerOptions: { + persistAuthorization: true + } + }); } diff --git a/back/tsconfig.json b/back/tsconfig.json index 5485d9d..95f5641 100644 --- a/back/tsconfig.json +++ b/back/tsconfig.json @@ -16,7 +16,6 @@ "noImplicitAny": false, "strictBindCallApply": false, "forceConsistentCasingInFileNames": false, - "noFallthroughCasesInSwitch": false, - "esModuleInterop": true + "noFallthroughCasesInSwitch": false } } From f19cddb81bc94afced52e3488ce5039c592315a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 22 Nov 2023 10:54:07 +0900 Subject: [PATCH 071/185] Update user.dto.ts --- back/src/modules/auth/dto/user.dto.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/back/src/modules/auth/dto/user.dto.ts b/back/src/modules/auth/dto/user.dto.ts index 67d0b1c..bbba6bd 100644 --- a/back/src/modules/auth/dto/user.dto.ts +++ b/back/src/modules/auth/dto/user.dto.ts @@ -1,21 +1,21 @@ -import { - IsString, - IsNumber, - IsUUID, - IsNotEmpty -} from '@nestjs/class-validator'; +import { IsString, IsNumber, IsNotEmpty } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class UserDto { + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '유저 pk id' }) + readonly id: number; + @IsString() @IsNotEmpty() @ApiProperty({ type: String, description: '사용자 이름' }) readonly name: string; - @IsUUID('4') + @IsString() @IsNotEmpty() - @ApiProperty({ format: 'uuid', description: 'Oauth에서 주는 값' }) - readonly id: string; + @ApiProperty({ type: String, description: 'Oauth에서 주는 값' }) + readonly uuid: string; @IsNumber() @IsNotEmpty() @@ -35,3 +35,4 @@ export class UserDto { @ApiProperty({ type: Number, description: '메시지 갯수' }) readonly message_count: number; } + From 8ea45d550dc97da9b6e7268bee9caae6f662f27c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 22 Nov 2023 11:05:29 +0900 Subject: [PATCH 072/185] Update auth.service.ts --- back/src/modules/auth/auth.service.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index 0f93e57..ab6bf93 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -11,8 +11,9 @@ export class AuthService { // Example data, replace with actual data from your logic const access_token = 'your-access-token'; const userDto: UserDto = { + id: 1, name: '김찬우', - id: 'Oauth에서 주는 값', + uuid: 'Oauth에서 주는 값', snowball_count: 3, snowball_list: [ '32413434-32a2-2342-3242-3g23-413oye3', From 635da839c21ad32e56b1a9a350eca5d293187e60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 22 Nov 2023 15:06:16 +0900 Subject: [PATCH 073/185] =?UTF-8?q?fix:=20api=20=EB=AA=85=EC=84=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/main.ts | 11 ---------- back/src/modules/auth/auth.service.ts | 11 +++++----- .../modules/auth/dto/response/res-info.dto.ts | 20 +++++++------------ back/src/modules/auth/dto/user.dto.ts | 18 ++++++++--------- back/src/modules/auth/kakao-auth.strategy.ts | 5 +++-- 5 files changed, 25 insertions(+), 40 deletions(-) diff --git a/back/src/main.ts b/back/src/main.ts index cf8301a..deca767 100644 --- a/back/src/main.ts +++ b/back/src/main.ts @@ -1,20 +1,9 @@ import { NestFactory } from '@nestjs/core'; import { setupSwagger } from 'src/util/swagger'; import { AppModule } from './app.module'; -import * as expressBasicAuth from 'express-basic-auth'; async function bootstrap() { const app = await NestFactory.create(AppModule); - app.use( - //이 부분 추가 - ['/docs'], // docs(swagger end point)에 진입시 - expressBasicAuth({ - challenge: true, - users: { - [process.env.SWAGGER_USER]: process.env.SWAGGER_PASSWORD // 지정된 ID/비밀번호 - } - }) - ); setupSwagger(app); await app.listen(3000); } diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index 0f93e57..212963d 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -9,10 +9,11 @@ export class AuthService { async createInfo(profile: any): Promise { if (profile) { // Example data, replace with actual data from your logic - const access_token = 'your-access-token'; + const jwt_token = 'your-jwt-token'; const userDto: UserDto = { + id: 1, name: '김찬우', - id: 'Oauth에서 주는 값', + uuid: 'Oauth에서 주는 값', snowball_count: 3, snowball_list: [ '32413434-32a2-2342-3242-3g23-413oye3', @@ -64,9 +65,9 @@ export class AuthService { }; const resInfoDto: ResInfoDto = { - access_token, - user: [userDto], - main_snowball: [mainSnowballDto] + jwt_token, + user: userDto, + main_snowball: mainSnowballDto }; return resInfoDto; diff --git a/back/src/modules/auth/dto/response/res-info.dto.ts b/back/src/modules/auth/dto/response/res-info.dto.ts index 44bb941..60a1b9a 100644 --- a/back/src/modules/auth/dto/response/res-info.dto.ts +++ b/back/src/modules/auth/dto/response/res-info.dto.ts @@ -1,34 +1,28 @@ -import { IsString, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; +import { IsString, IsNotEmpty } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; import { UserDto } from '../user.dto'; import { SnowballDto } from '../../../snowball/dto/snowball.dto'; -import { Type } from '@nestjs/class-transformer'; export class ResInfoDto { @IsNotEmpty() @IsString() @ApiProperty({ type: String, - description: 'Bearer 타입의 OAuth 2.0 액세스 토큰', - example: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' + description: 'JWT 타입의 유저 토큰' }) - readonly access_token: string; + readonly jwt_token: string; @IsNotEmpty() - @ValidateNested({ each: true }) - @Type(() => UserDto) @ApiProperty({ type: UserDto, - description: '사용자 정보 배열' + description: '사용자 정보 ' }) - readonly user: UserDto[]; + readonly user: UserDto; @IsNotEmpty() - @ValidateNested({ each: true }) - @Type(() => SnowballDto) @ApiProperty({ type: SnowballDto, - description: '메인 스노우볼 정보 배열' + description: '메인 스노우볼 정보' }) - readonly main_snowball: SnowballDto[]; + readonly main_snowball: SnowballDto; } diff --git a/back/src/modules/auth/dto/user.dto.ts b/back/src/modules/auth/dto/user.dto.ts index 67d0b1c..16ce22d 100644 --- a/back/src/modules/auth/dto/user.dto.ts +++ b/back/src/modules/auth/dto/user.dto.ts @@ -1,21 +1,21 @@ -import { - IsString, - IsNumber, - IsUUID, - IsNotEmpty -} from '@nestjs/class-validator'; +import { IsString, IsNumber, IsNotEmpty } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class UserDto { + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '유저 pk id' }) + readonly id: number; + @IsString() @IsNotEmpty() @ApiProperty({ type: String, description: '사용자 이름' }) readonly name: string; - @IsUUID('4') + @IsString() @IsNotEmpty() - @ApiProperty({ format: 'uuid', description: 'Oauth에서 주는 값' }) - readonly id: string; + @ApiProperty({ type: String, description: 'Oauth에서 주는 값' }) + readonly uuid: string; @IsNumber() @IsNotEmpty() diff --git a/back/src/modules/auth/kakao-auth.strategy.ts b/back/src/modules/auth/kakao-auth.strategy.ts index e46f2f8..3f7dd8b 100644 --- a/back/src/modules/auth/kakao-auth.strategy.ts +++ b/back/src/modules/auth/kakao-auth.strategy.ts @@ -22,9 +22,10 @@ export class KakaoAuthStrategy extends PassportStrategy(Strategy, 'kakao') { done: any ) { try { - console.log(profile); const user = { - profile + profile, + accessToken, + refreshToken }; done(null, user); } catch (err) { From 90fe9422f52ca962709c6b87807134e915c01a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 22 Nov 2023 15:08:00 +0900 Subject: [PATCH 074/185] =?UTF-8?q?fix:=20user=20entity=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{snowball => auth}/entity/user.entity.ts | 2 +- back/src/modules/message/message.module.ts | 2 +- back/src/modules/message/message.service.ts | 2 +- .../snowball/entity/snowball.entity.ts | 2 +- package-lock.json | 55 ++++++++++++++++++- package.json | 3 +- 6 files changed, 60 insertions(+), 6 deletions(-) rename back/src/modules/{snowball => auth}/entity/user.entity.ts (86%) diff --git a/back/src/modules/snowball/entity/user.entity.ts b/back/src/modules/auth/entity/user.entity.ts similarity index 86% rename from back/src/modules/snowball/entity/user.entity.ts rename to back/src/modules/auth/entity/user.entity.ts index 31e64bc..e363b5d 100644 --- a/back/src/modules/snowball/entity/user.entity.ts +++ b/back/src/modules/auth/entity/user.entity.ts @@ -5,7 +5,7 @@ import { OneToMany, CreateDateColumn } from 'typeorm'; -import { SnowballEntity } from './snowball.entity'; +import { SnowballEntity } from '../../snowball/entity/snowball.entity'; @Entity({ name: 'user' }) export class UserEntity { diff --git a/back/src/modules/message/message.module.ts b/back/src/modules/message/message.module.ts index 1618e70..c0f2df8 100644 --- a/back/src/modules/message/message.module.ts +++ b/back/src/modules/message/message.module.ts @@ -3,7 +3,7 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { MessageController } from './message.controller'; import { MessageService } from './message.service'; import { MessageEntity } from './entity/message.entity'; -import { UserEntity } from '../snowball/entity/user.entity'; +import { UserEntity } from '../auth/entity/user.entity'; import { SnowballEntity } from '../snowball/entity/snowball.entity'; @Module({ imports: [ diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 3c165e9..0f5c858 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -4,7 +4,7 @@ import { Repository } from 'typeorm'; import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; import { ReqDeleteMessageDto } from './dto/request/req-delete-message.dto'; import { MessageEntity } from './entity/message.entity'; -import { UserEntity } from '../snowball/entity/user.entity'; +import { UserEntity } from '../auth/entity/user.entity'; import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; import { MessageDto } from './dto/message.dto'; diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index be05c67..03c942d 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -11,7 +11,7 @@ import { JoinColumn, BeforeInsert } from 'typeorm'; -import { UserEntity } from './user.entity'; +import { UserEntity } from '../../auth/entity/user.entity'; import { SnowballDecorationEntity } from './snowball-decoration.entity'; import { MessageEntity } from '../../message/entity/message.entity'; diff --git a/package-lock.json b/package-lock.json index 96c6430..b940760 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2,5 +2,58 @@ "name": "ssock", "lockfileVersion": 3, "requires": true, - "packages": {} + "packages": { + "": { + "dependencies": { + "@nestjs/class-validator": "^0.13.4", + "express-basic-auth": "^1.2.1" + } + }, + "node_modules/@nestjs/class-validator": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/@nestjs/class-validator/-/class-validator-0.13.4.tgz", + "integrity": "sha512-/mqZL36LJ5uV5WDhi87Cd52IssuO+SStaOr2+6sBsvCCGUWkoJes4Wwzmm3m/gdHH+tsNxX60sVSzYcU6hAy9Q==", + "dependencies": { + "libphonenumber-js": "^1.9.43", + "validator": "^13.7.0" + } + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express-basic-auth": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/express-basic-auth/-/express-basic-auth-1.2.1.tgz", + "integrity": "sha512-L6YQ1wQ/mNjVLAmK3AG1RK6VkokA1BIY6wmiH304Xtt/cLTps40EusZsU1Uop+v9lTDPxdtzbFmdXfFO3KEnwA==", + "dependencies": { + "basic-auth": "^2.0.1" + } + }, + "node_modules/libphonenumber-js": { + "version": "1.10.49", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.49.tgz", + "integrity": "sha512-gvLtyC3tIuqfPzjvYLH9BmVdqzGDiSi4VjtWe2fAgSdBf0yt8yPmbNnRIHNbR5IdtVkm0ayGuzwQKTWmU0hdjQ==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "engines": { + "node": ">= 0.10" + } + } + } } diff --git a/package.json b/package.json index 7ed19b9..f146ee3 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "dependencies": { - "@nestjs/class-validator": "^0.13.4" + "@nestjs/class-validator": "^0.13.4", + "express-basic-auth": "^1.2.1" } } From 127c1e933658558c84fce245f58317978a58d358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 22 Nov 2023 16:03:26 +0900 Subject: [PATCH 075/185] =?UTF-8?q?feat:=20strategy=20=EB=B0=98=ED=99=98?= =?UTF-8?q?=EA=B0=92=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20user=20dto?= =?UTF-8?q?=EC=97=90=EC=84=9C=20snowball=20id=EB=8F=84=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/package-lock.json | 218 +++++++++++++++++- back/package.json | 1 + back/src/modules/auth/auth.controller.ts | 4 +- back/src/modules/auth/auth.module.ts | 15 +- back/src/modules/auth/auth.service.ts | 136 +++++------ back/src/modules/auth/dto/user.dto.ts | 16 +- .../{ => strategy}/google-auth.strategy.ts | 11 +- .../{ => strategy}/kakao-auth.strategy.ts | 8 +- .../{ => strategy}/naver-auth.strategy.ts | 13 +- 9 files changed, 324 insertions(+), 98 deletions(-) rename back/src/modules/auth/{ => strategy}/google-auth.strategy.ts (86%) rename back/src/modules/auth/{ => strategy}/kakao-auth.strategy.ts (83%) rename back/src/modules/auth/{ => strategy}/naver-auth.strategy.ts (72%) diff --git a/back/package-lock.json b/back/package-lock.json index d11dab3..7a694ab 100644 --- a/back/package-lock.json +++ b/back/package-lock.json @@ -13,6 +13,7 @@ "@nestjs/class-validator": "^0.13.4", "@nestjs/common": "^10.0.0", "@nestjs/core": "^10.0.0", + "@nestjs/jwt": "^10.2.0", "@nestjs/passport": "^10.0.2", "@nestjs/platform-express": "^10.0.0", "@nestjs/swagger": "^7.1.16", @@ -1767,6 +1768,18 @@ } } }, + "node_modules/@nestjs/jwt": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-10.2.0.tgz", + "integrity": "sha512-x8cG90SURkEiLOehNaN2aRlotxT0KZESUliOPKKnjWiyJOcWurkF3w345WOX0P4MgFzUjGoZ1Sy0aZnxeihT0g==", + "dependencies": { + "@types/jsonwebtoken": "9.0.5", + "jsonwebtoken": "9.0.2" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0" + } + }, "node_modules/@nestjs/mapped-types": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.3.tgz", @@ -2298,6 +2311,14 @@ "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", "dev": true }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.5.tgz", + "integrity": "sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/mime": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.4.tgz", @@ -2308,7 +2329,6 @@ "version": "20.8.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", - "devOptional": true, "dependencies": { "undici-types": "~5.26.4" } @@ -3396,6 +3416,11 @@ "ieee754": "^1.1.13" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -4475,6 +4500,14 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -6923,6 +6956,46 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -7003,6 +7076,36 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -7015,6 +7118,11 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -10234,8 +10342,7 @@ "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==", - "devOptional": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/unique-filename": { "version": "1.1.1", @@ -11999,6 +12106,15 @@ "uid": "2.0.2" } }, + "@nestjs/jwt": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-10.2.0.tgz", + "integrity": "sha512-x8cG90SURkEiLOehNaN2aRlotxT0KZESUliOPKKnjWiyJOcWurkF3w345WOX0P4MgFzUjGoZ1Sy0aZnxeihT0g==", + "requires": { + "@types/jsonwebtoken": "9.0.5", + "jsonwebtoken": "9.0.2" + } + }, "@nestjs/mapped-types": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.3.tgz", @@ -12410,6 +12526,14 @@ "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", "dev": true }, + "@types/jsonwebtoken": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.5.tgz", + "integrity": "sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==", + "requires": { + "@types/node": "*" + } + }, "@types/mime": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.4.tgz", @@ -12420,7 +12544,6 @@ "version": "20.8.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", - "devOptional": true, "requires": { "undici-types": "~5.26.4" } @@ -13252,6 +13375,11 @@ "ieee754": "^1.1.13" } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -14003,6 +14131,14 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -15854,6 +15990,42 @@ "universalify": "^2.0.0" } }, + "jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + } + }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -15916,6 +16088,36 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -15928,6 +16130,11 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -18239,8 +18446,7 @@ "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==", - "devOptional": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "unique-filename": { "version": "1.1.1", diff --git a/back/package.json b/back/package.json index baa6057..86372b9 100644 --- a/back/package.json +++ b/back/package.json @@ -24,6 +24,7 @@ "@nestjs/class-validator": "^0.13.4", "@nestjs/common": "^10.0.0", "@nestjs/core": "^10.0.0", + "@nestjs/jwt": "^10.2.0", "@nestjs/passport": "^10.0.2", "@nestjs/platform-express": "^10.0.0", "@nestjs/swagger": "^7.1.16", diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index 59cc64b..1f49869 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -105,8 +105,8 @@ export class AuthController { description: 'Internal Server Error' }) async kakaoLoginCallBack(@Req() req): Promise { - const profile: string = req.user.profile; - const result = this.authService.createInfo(profile); + const userInfo = req.user; + const result = this.authService.createInfo(userInfo); return result; } } diff --git a/back/src/modules/auth/auth.module.ts b/back/src/modules/auth/auth.module.ts index 839971e..45de3c7 100644 --- a/back/src/modules/auth/auth.module.ts +++ b/back/src/modules/auth/auth.module.ts @@ -1,13 +1,20 @@ import { Module } from '@nestjs/common'; -import { GoogleAuthStrategy } from './google-auth.strategy'; -import { NaverAuthStrategy } from './naver-auth.strategy'; -import { KakaoAuthStrategy } from './kakao-auth.strategy'; +import { GoogleAuthStrategy } from './strategy/google-auth.strategy'; +import { NaverAuthStrategy } from './strategy/naver-auth.strategy'; +import { KakaoAuthStrategy } from './strategy/kakao-auth.strategy'; import { AuthController } from './auth.controller'; import { PassportModule } from '@nestjs/passport'; import { AuthService } from './auth.service'; +import { JwtModule } from '@nestjs/jwt'; @Module({ - imports: [PassportModule], + imports: [ + PassportModule, + JwtModule.register({ + secret: 'SECRET', + signOptions: { expiresIn: '300s' } + }) + ], providers: [ GoogleAuthStrategy, NaverAuthStrategy, diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index 212963d..73be5ba 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -1,78 +1,78 @@ -import { Injectable, UnauthorizedException } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { ResInfoDto } from './dto/response/res-info.dto'; import { UserDto } from './dto/user.dto'; import { SnowballDto } from '../snowball/dto/snowball.dto'; +import { JwtService } from '@nestjs/jwt'; @Injectable() export class AuthService { - constructor() {} + constructor(private readonly jwtService: JwtService) {} - async createInfo(profile: any): Promise { - if (profile) { - // Example data, replace with actual data from your logic - const jwt_token = 'your-jwt-token'; - const userDto: UserDto = { - id: 1, - name: '김찬우', - uuid: 'Oauth에서 주는 값', - snowball_count: 3, - snowball_list: [ - '32413434-32a2-2342-3242-3g23-413oye3', - '32413434-32a2-2342-3242-3g23-413oye3', - '32413434-32a2-2342-3242-3g23-413oye3' - ], - message_count: 123 - }; - const mainSnowballDto: SnowballDto = { - title: '나만의 스노우볼1', - id: 1, - uuid: '32413434-32a2-2342-3242-3g23-413oye3', - message_private: null, - // message_count_private: null, - deco_list: [ - { - decoration_id: 15, - decoration_color: '#FFFFFF', - location: 13 - }, - { - decoration_id: 12, - decoration_color: '#FFFFFF', - location: 14 - } - ], - message_list: [ - { - id: 1, - decoration_id: 15, - decoration_color: '#FFFFFF', - letter_id: 1, - content: '편지 내용', - sender: '널 좋아하는 사람', - opened: null, - created: new Date('2023-12-30T17:35:31Z') - }, - { - id: 2, - decoration_id: 15, - decoration_color: '#FFFFFF', - letter_id: 1, - content: '편지 내용', - sender: '찬우를 사랑하는 사람', - opened: null, - created: new Date('2023-12-30T17:35:31Z') - } - ] - }; + async createInfo(user: any): Promise { + const jwt_token = this.generateJwtToken(user); + const userDto: UserDto = { + id: 1, + name: '김찬우', + auth_id: 'Oauth에서 주는 값', + snowball_count: 3, + snowball_list: [ + { id: 1, uuid: '32413434-32a2-2342-3242-3g23-413oye3' }, + { id: 2, uuid: '32413434-32a2-2342-3242-3g23-413oye4' }, + { id: 3, uuid: '32413434-32a2-2342-3242-3g23-413oye5' } + ], + message_count: 123 + }; + const mainSnowballDto: SnowballDto = { + title: '나만의 스노우볼1', + id: 1, + uuid: '32413434-32a2-2342-3242-3g23-413oye3', + message_private: null, + deco_list: [ + { + decoration_id: 15, + decoration_color: '#FFFFFF', + location: 13 + }, + { + decoration_id: 12, + decoration_color: '#FFFFFF', + location: 14 + } + ], + message_list: [ + { + id: 1, + decoration_id: 15, + decoration_color: '#FFFFFF', + letter_id: 1, + content: '편지 내용', + sender: '널 좋아하는 사람', + opened: null, + created: new Date('2023-12-30T17:35:31Z') + }, + { + id: 2, + decoration_id: 15, + decoration_color: '#FFFFFF', + letter_id: 1, + content: '편지 내용', + sender: '찬우를 사랑하는 사람', + opened: null, + created: new Date('2023-12-30T17:35:31Z') + } + ] + }; - const resInfoDto: ResInfoDto = { - jwt_token, - user: userDto, - main_snowball: mainSnowballDto - }; + const resInfoDto: ResInfoDto = { + jwt_token, + user: userDto, + main_snowball: mainSnowballDto + }; - return resInfoDto; - } else { - throw new UnauthorizedException('Failed to authenticate with Google'); - } + return resInfoDto; + } + + generateJwtToken(user: any): string { + const payload = { sub: user.id, username: user.username }; + return this.jwtService.sign(payload); } } diff --git a/back/src/modules/auth/dto/user.dto.ts b/back/src/modules/auth/dto/user.dto.ts index bbba6bd..52f5bcb 100644 --- a/back/src/modules/auth/dto/user.dto.ts +++ b/back/src/modules/auth/dto/user.dto.ts @@ -15,7 +15,7 @@ export class UserDto { @IsString() @IsNotEmpty() @ApiProperty({ type: String, description: 'Oauth에서 주는 값' }) - readonly uuid: string; + readonly auth_id: string; @IsNumber() @IsNotEmpty() @@ -24,11 +24,17 @@ export class UserDto { @IsNotEmpty() @ApiProperty({ - type: [String], - format: 'uuid', - description: '스노우볼 UUID 리스트' + type: 'array', + items: { + type: 'object', + properties: { + id: { type: 'number' }, + uuid: { type: 'string' } + } + }, + description: '스노우볼 key-value 리스트' }) - readonly snowball_list: string[]; + readonly snowball_list: { id: number; uuid: string }[]; @IsNumber() @IsNotEmpty() diff --git a/back/src/modules/auth/google-auth.strategy.ts b/back/src/modules/auth/strategy/google-auth.strategy.ts similarity index 86% rename from back/src/modules/auth/google-auth.strategy.ts rename to back/src/modules/auth/strategy/google-auth.strategy.ts index a9ae90b..089d943 100644 --- a/back/src/modules/auth/google-auth.strategy.ts +++ b/back/src/modules/auth/strategy/google-auth.strategy.ts @@ -8,8 +8,7 @@ export class GoogleAuthStrategy extends PassportStrategy(Strategy, 'google') { super({ clientID: `${process.env.GOOGLE_CLIENT_ID}`, clientSecret: `${process.env.GOOGLE_SECRET}`, - callbackURL: 'http://localhost:3000/auth/google/redirect', // redirect_uri - passReqToCallback: true, + callbackURL: 'http://localhost:3000/auth/google/redirect', scope: ['profile'] }); } @@ -20,16 +19,18 @@ export class GoogleAuthStrategy extends PassportStrategy(Strategy, 'google') { }; } async validate( - request: any, accessToken: string, refreshToken: string, profile: Profile, done: any ) { try { - console.log(profile); const user = { - profile + id: profile.id, + name: profile.displayName, + provider: profile.provider, + accessToken, + refreshToken }; done(null, user); } catch (err) { diff --git a/back/src/modules/auth/kakao-auth.strategy.ts b/back/src/modules/auth/strategy/kakao-auth.strategy.ts similarity index 83% rename from back/src/modules/auth/kakao-auth.strategy.ts rename to back/src/modules/auth/strategy/kakao-auth.strategy.ts index 3f7dd8b..8a2f043 100644 --- a/back/src/modules/auth/kakao-auth.strategy.ts +++ b/back/src/modules/auth/strategy/kakao-auth.strategy.ts @@ -9,21 +9,23 @@ export class KakaoAuthStrategy extends PassportStrategy(Strategy, 'kakao') { clientID: `${process.env.KAKAO_CLIENT_ID}`, clientSecret: `${process.env.KAKAO_SECRET}`, callbackURL: 'http://localhost:3000/auth/kakao/redirect', // redirect_uri - passReqToCallback: true, + passReqToCallback: false, scope: ['profile_nickname'] }); } async validate( - request: any, accessToken: string, refreshToken: string, profile: Profile, done: any ) { try { + console.log(profile); const user = { - profile, + id: profile.id, + name: profile.displayName, + provider: profile.provider, accessToken, refreshToken }; diff --git a/back/src/modules/auth/naver-auth.strategy.ts b/back/src/modules/auth/strategy/naver-auth.strategy.ts similarity index 72% rename from back/src/modules/auth/naver-auth.strategy.ts rename to back/src/modules/auth/strategy/naver-auth.strategy.ts index 8032bfa..be56d04 100644 --- a/back/src/modules/auth/naver-auth.strategy.ts +++ b/back/src/modules/auth/strategy/naver-auth.strategy.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; -import { Profile, Strategy } from 'passport-naver-v2'; +import { Profile as NaverProfile, Strategy } from 'passport-naver-v2'; @Injectable() export class NaverAuthStrategy extends PassportStrategy(Strategy, 'naver') { @@ -9,22 +9,25 @@ export class NaverAuthStrategy extends PassportStrategy(Strategy, 'naver') { clientID: `${process.env.NAVER_CLIENT_ID}`, clientSecret: `${process.env.NAVER_SECRET}`, callbackURL: 'http://localhost:3000/auth/naver/redirect', // redirect_uri - passReqToCallback: true, + passReqToCallback: false, scope: ['profile'] }); } async validate( - request: any, accessToken: string, refreshToken: string, - profile: Profile, + profile: NaverProfile, done: any ) { try { console.log(profile); const user = { - profile + id: profile.id, + name: profile.name, + provider: profile.provider, + accessToken, + refreshToken }; done(null, user); } catch (err) { From 16fd33141bf996c16a5e7ff0875639a2131ea218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 22 Nov 2023 16:13:30 +0900 Subject: [PATCH 076/185] =?UTF-8?q?feat:=20auth=EB=AA=A8=EB=93=88=EC=97=90?= =?UTF-8?q?=20snowball=20service=20=EC=A3=BC=EC=9E=85=ED=95=98=EC=97=AC=20?= =?UTF-8?q?snowballDto=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.module.ts | 13 +++++++- back/src/modules/auth/auth.service.ts | 48 ++++----------------------- 2 files changed, 19 insertions(+), 42 deletions(-) diff --git a/back/src/modules/auth/auth.module.ts b/back/src/modules/auth/auth.module.ts index 45de3c7..535d297 100644 --- a/back/src/modules/auth/auth.module.ts +++ b/back/src/modules/auth/auth.module.ts @@ -6,9 +6,19 @@ import { AuthController } from './auth.controller'; import { PassportModule } from '@nestjs/passport'; import { AuthService } from './auth.service'; import { JwtModule } from '@nestjs/jwt'; +import { SnowballService } from '../snowball/snowball.service'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { SnowballEntity } from '../snowball/entity/snowball.entity'; +import { UserEntity } from './entity/user.entity'; +import { SnowballDecorationEntity } from '../snowball/entity/snowball-decoration.entity'; @Module({ imports: [ + TypeOrmModule.forFeature([ + SnowballEntity, + UserEntity, + SnowballDecorationEntity + ]), PassportModule, JwtModule.register({ secret: 'SECRET', @@ -19,7 +29,8 @@ import { JwtModule } from '@nestjs/jwt'; GoogleAuthStrategy, NaverAuthStrategy, KakaoAuthStrategy, - AuthService + AuthService, + SnowballService ], controllers: [AuthController] }) diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index 73be5ba..35988e9 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -3,9 +3,13 @@ import { ResInfoDto } from './dto/response/res-info.dto'; import { UserDto } from './dto/user.dto'; import { SnowballDto } from '../snowball/dto/snowball.dto'; import { JwtService } from '@nestjs/jwt'; +import { SnowballService } from '../snowball/snowball.service'; @Injectable() export class AuthService { - constructor(private readonly jwtService: JwtService) {} + constructor( + private readonly jwtService: JwtService, + private readonly snowballService: SnowballService + ) {} async createInfo(user: any): Promise { const jwt_token = this.generateJwtToken(user); @@ -21,46 +25,8 @@ export class AuthService { ], message_count: 123 }; - const mainSnowballDto: SnowballDto = { - title: '나만의 스노우볼1', - id: 1, - uuid: '32413434-32a2-2342-3242-3g23-413oye3', - message_private: null, - deco_list: [ - { - decoration_id: 15, - decoration_color: '#FFFFFF', - location: 13 - }, - { - decoration_id: 12, - decoration_color: '#FFFFFF', - location: 14 - } - ], - message_list: [ - { - id: 1, - decoration_id: 15, - decoration_color: '#FFFFFF', - letter_id: 1, - content: '편지 내용', - sender: '널 좋아하는 사람', - opened: null, - created: new Date('2023-12-30T17:35:31Z') - }, - { - id: 2, - decoration_id: 15, - decoration_color: '#FFFFFF', - letter_id: 1, - content: '편지 내용', - sender: '찬우를 사랑하는 사람', - opened: null, - created: new Date('2023-12-30T17:35:31Z') - } - ] - }; + const mainSnowballDto: SnowballDto = + await this.snowballService.getSnowball(1); const resInfoDto: ResInfoDto = { jwt_token, From 8b6a3e1649a30fbf9b2c51239cceeff28869c671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 22 Nov 2023 16:19:49 +0900 Subject: [PATCH 077/185] =?UTF-8?q?feat:=20auth.service=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.service.ts | 32 ++++++++++++++++++--------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index 35988e9..b12f963 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -4,16 +4,36 @@ import { UserDto } from './dto/user.dto'; import { SnowballDto } from '../snowball/dto/snowball.dto'; import { JwtService } from '@nestjs/jwt'; import { SnowballService } from '../snowball/snowball.service'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { UserEntity } from './entity/user.entity'; @Injectable() export class AuthService { constructor( + @InjectRepository(UserEntity) + private readonly UserRepository: Repository, private readonly jwtService: JwtService, private readonly snowballService: SnowballService ) {} async createInfo(user: any): Promise { const jwt_token = this.generateJwtToken(user); - const userDto: UserDto = { + const userDto: UserDto = await this.createUserDto(); + const mainSnowballDto: SnowballDto = + await this.snowballService.getSnowball(1); + + const resInfoDto: ResInfoDto = { + jwt_token, + user: userDto, + main_snowball: mainSnowballDto + }; + + return resInfoDto; + } + + async createUserDto(): Promise { + // To Do : 쿼리짜기.. + return { id: 1, name: '김찬우', auth_id: 'Oauth에서 주는 값', @@ -25,16 +45,6 @@ export class AuthService { ], message_count: 123 }; - const mainSnowballDto: SnowballDto = - await this.snowballService.getSnowball(1); - - const resInfoDto: ResInfoDto = { - jwt_token, - user: userDto, - main_snowball: mainSnowballDto - }; - - return resInfoDto; } generateJwtToken(user: any): string { From 2498a3ad9877d2040cf6b46157341e293e046184 Mon Sep 17 00:00:00 2001 From: peageon Date: Wed, 22 Nov 2023 17:44:17 +0900 Subject: [PATCH 078/185] =?UTF-8?q?feat:=20JWTGuard=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20/=20.env=EC=97=90=20JWT=5FSECRET=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.guard.ts | 37 +++++++++++++++++++++++++++ back/src/modules/auth/auth.module.ts | 2 +- back/src/modules/auth/auth.service.ts | 2 +- 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 back/src/modules/auth/auth.guard.ts diff --git a/back/src/modules/auth/auth.guard.ts b/back/src/modules/auth/auth.guard.ts new file mode 100644 index 0000000..48ba6a1 --- /dev/null +++ b/back/src/modules/auth/auth.guard.ts @@ -0,0 +1,37 @@ +import { + CanActivate, + ExecutionContext, + Injectable, + Req, + UnauthorizedException +} from '@nestjs/common'; +import { JwtService } from '@nestjs/jwt'; +import { Request } from 'express'; + +@Injectable() +export class JWTGuard implements CanActivate { + constructor(private readonly jwtService: JwtService) {} + + async canActivate(context: ExecutionContext): Promise { + const request = context.switchToHttp().getRequest(); + const token = this.extractTokenFromHeader(request); + if (!token) { + throw new UnauthorizedException(); + } + try { + const payload = await this.jwtService.verify(token, { + secret: process.env.JWT_SECRET + }); + // route 핸들러에서 request.user로 사용할 수 있도록 넣어줌 + request['user'] = payload; + } catch { + throw new UnauthorizedException(); + } + return true; + } + + private extractTokenFromHeader(@Req() req: Request): string | undefined { + const [type, token] = req.headers.authorization?.split(' ') ?? []; + return type === 'Bearer' ? token : null; + } +} diff --git a/back/src/modules/auth/auth.module.ts b/back/src/modules/auth/auth.module.ts index 535d297..e1c6f62 100644 --- a/back/src/modules/auth/auth.module.ts +++ b/back/src/modules/auth/auth.module.ts @@ -21,7 +21,7 @@ import { SnowballDecorationEntity } from '../snowball/entity/snowball-decoration ]), PassportModule, JwtModule.register({ - secret: 'SECRET', + secret: process.env.JWT_SECRET, signOptions: { expiresIn: '300s' } }) ], diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index b12f963..7d4a33d 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -48,7 +48,7 @@ export class AuthService { } generateJwtToken(user: any): string { - const payload = { sub: user.id, username: user.username }; + const payload = { userid: user.id, username: user.username }; return this.jwtService.sign(payload); } } From 5413e02bd88adf4f8a4e18118954e723fd19762f Mon Sep 17 00:00:00 2001 From: peageon Date: Wed, 22 Nov 2023 22:06:38 +0900 Subject: [PATCH 079/185] =?UTF-8?q?feat:=20restful=ED=95=98=EA=B2=8C=20api?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/req-create-message.dto.ts | 5 ---- .../src/modules/message/message.controller.ts | 11 +++++---- back/src/modules/message/message.service.ts | 5 ++-- .../dto/request/req-update-decoration.dto.ts | 10 ++++---- .../dto/request/req-update-snowball.dto.ts | 12 +--------- .../modules/snowball/snowball.controller.ts | 24 +++++++++++++------ back/src/modules/snowball/snowball.service.ts | 10 ++++---- 7 files changed, 39 insertions(+), 38 deletions(-) diff --git a/back/src/modules/message/dto/request/req-create-message.dto.ts b/back/src/modules/message/dto/request/req-create-message.dto.ts index 175a900..f78c20f 100644 --- a/back/src/modules/message/dto/request/req-create-message.dto.ts +++ b/back/src/modules/message/dto/request/req-create-message.dto.ts @@ -2,11 +2,6 @@ import { IsString, IsNotEmpty, IsNumber } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class ReqCreateMessageDto { - @IsNotEmpty() - @IsNumber() - @ApiProperty({ type: Number, description: '스노우볼 id' }) - readonly snowball_id: number; - @IsString() @IsNotEmpty() @ApiProperty({ type: String, description: '익명 사용자 닉네임(From)' }) diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 61d2480..163981e 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -19,7 +19,7 @@ import { MessageDto } from './dto/message.dto'; export class MessageController { constructor(private readonly messageService: MessageService) {} - @Post() + @Post('/:snowball_id') @HttpCode(201) @ApiOperation({ summary: '메세지 생성 API', @@ -36,10 +36,13 @@ export class MessageController { description: 'Insert Fail' }) async createMessage( + @Param('snowball_id') snowball_id: number, @Body() createMessageDto: ReqCreateMessageDto ): Promise { - const resCreateMessage = - await this.messageService.createMessage(createMessageDto); + const resCreateMessage = await this.messageService.createMessage( + createMessageDto, + snowball_id + ); return resCreateMessage; } @@ -58,7 +61,7 @@ export class MessageController { await this.messageService.deleteMessage(deleteMessageDto); } - @Get('all/:user_id/') + @Get('/:user_id') @HttpCode(200) @ApiOperation({ summary: '메세지 조회 API', diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 0f5c858..e294c57 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -17,10 +17,11 @@ export class MessageService { private readonly messageRepository: Repository ) {} async createMessage( - createMessageDto: ReqCreateMessageDto + createMessageDto: ReqCreateMessageDto, + snowball_id: number ): Promise { const messageEntity = this.messageRepository.create({ - snowball_id: createMessageDto.snowball_id, + snowball_id: snowball_id, sender: createMessageDto.sender, content: createMessageDto.content, decoration_id: createMessageDto.decoration_id, diff --git a/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts b/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts index 6724841..89f67b4 100644 --- a/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts +++ b/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts @@ -1,13 +1,13 @@ -import { IsNumber, IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; +import { IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; import { DecorationSnowballDto } from '../decoration-snowball.dto'; export class ReqUpdateSnowballDecoDto { - @IsNotEmpty() - @IsNumber() - @ApiProperty({ type: Number, description: '스노우볼 id' }) - readonly snowball_id: number; + // @IsNotEmpty() + // @IsNumber() + // @ApiProperty({ type: Number, description: '스노우볼 id' }) + // readonly snowball_id: number; @IsNotEmpty() @ValidateNested({ each: true }) diff --git a/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts b/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts index 3b4e124..d1519d2 100644 --- a/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts @@ -1,17 +1,7 @@ -import { - IsString, - IsNumber, - IsNotEmpty, - IsBoolean -} from '@nestjs/class-validator'; +import { IsString, IsNotEmpty, IsBoolean } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class ReqUpdateSnowballDto { - @IsNotEmpty() - @IsNumber() - @ApiProperty({ type: Number, description: '스노우볼 id' }) - readonly snowball_id: number; - @IsString() @IsNotEmpty() @ApiProperty({ type: String, description: '스노우볼 제목' }) diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index bf14346..14d448c 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -45,7 +45,7 @@ export class SnowballController { return snowball; } - @Put('/decoration') + @Put('/:snowball_id/decoration') @HttpCode(200) @ApiResponse({ status: 200, @@ -57,14 +57,18 @@ export class SnowballController { description: '스노우볼의 데코레이션들을 업데이트 해줍니다.' }) @ApiBody({ type: ReqUpdateSnowballDecoDto }) - updateSnowballDecor(@Body() updateSnowballDecoDto: ReqUpdateSnowballDecoDto) { + updateSnowballDecor( + @Param('snowball_id') snowball_id: number, + @Body() updateSnowballDecoDto: ReqUpdateSnowballDecoDto + ) { const snowballDecoration = this.snowballService.updateSnowballDeco( - updateSnowballDecoDto + updateSnowballDecoDto, + snowball_id ); return snowballDecoration; } - @Put() + @Put('/:snowball_id') @HttpCode(200) @ApiResponse({ status: 200, @@ -76,12 +80,18 @@ export class SnowballController { description: '스노우볼에의 정보를 업데이트 해줍니다.' }) @ApiBody({ type: ReqUpdateSnowballDto }) - updateSnowball(@Body() updateSnowballDto: ReqUpdateSnowballDto) { - const snowball = this.snowballService.updateSnowball(updateSnowballDto); + updateSnowball( + @Param('snowball_id') snowball_id: number, + @Body() updateSnowballDto: ReqUpdateSnowballDto + ) { + const snowball = this.snowballService.updateSnowball( + updateSnowballDto, + snowball_id + ); return snowball; } - @Get('/info/:snowball_id') + @Get('/:snowball_id') @HttpCode(200) @ApiResponse({ status: 200, diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 84e6098..e738994 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -64,9 +64,10 @@ export class SnowballService { } async updateSnowballDeco( - updateSnowballDecoDto: ReqUpdateSnowballDecoDto + updateSnowballDecoDto: ReqUpdateSnowballDecoDto, + snowball_id: number ): Promise { - const { snowball_id, deco_list } = updateSnowballDecoDto; + const { deco_list } = updateSnowballDecoDto; // Delete all decorations await this.decorationRepository.delete({ @@ -87,9 +88,10 @@ export class SnowballService { } async updateSnowball( - updateSnowballDto: ReqUpdateSnowballDto + updateSnowballDto: ReqUpdateSnowballDto, + snowball_id: number ): Promise { - const { snowball_id, title, message_private } = updateSnowballDto; + const { title, message_private } = updateSnowballDto; const updateResult = await this.snowballRepository .createQueryBuilder() From d7b42e56005e1dbc1234a7e9cdd739f2acf3dd1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Thu, 23 Nov 2023 03:11:09 +0900 Subject: [PATCH 080/185] fix:rebase test --- back/src/modules/auth/dto/user.dto.ts | 1 - .../snowball/dto/request/req-update-decoration.dto.ts | 5 ----- 2 files changed, 6 deletions(-) diff --git a/back/src/modules/auth/dto/user.dto.ts b/back/src/modules/auth/dto/user.dto.ts index 52f5bcb..2c2edb0 100644 --- a/back/src/modules/auth/dto/user.dto.ts +++ b/back/src/modules/auth/dto/user.dto.ts @@ -41,4 +41,3 @@ export class UserDto { @ApiProperty({ type: Number, description: '메시지 갯수' }) readonly message_count: number; } - diff --git a/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts b/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts index 89f67b4..fda9919 100644 --- a/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts +++ b/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts @@ -4,11 +4,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { DecorationSnowballDto } from '../decoration-snowball.dto'; export class ReqUpdateSnowballDecoDto { - // @IsNotEmpty() - // @IsNumber() - // @ApiProperty({ type: Number, description: '스노우볼 id' }) - // readonly snowball_id: number; - @IsNotEmpty() @ValidateNested({ each: true }) @Type(() => DecorationSnowballDto) From 0ab2cba8e95b95a54ee076603133de36902a0fe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Thu, 23 Nov 2023 03:13:33 +0900 Subject: [PATCH 081/185] =?UTF-8?q?fix:=20boolean=20=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EB=B0=8D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../snowball/dto/request/req-create-snowball.dto.ts | 2 +- .../snowball/dto/request/req-update-snowball.dto.ts | 2 +- .../snowball/dto/response/res-update-snowball.dto.ts | 2 +- back/src/modules/snowball/dto/snowball.dto.ts | 2 +- back/src/modules/snowball/snowball.service.ts | 12 ++++++------ 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts b/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts index 10d1d2a..8d2caea 100644 --- a/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts @@ -35,5 +35,5 @@ export class ReqCreateSnowballDto { type: Boolean, description: '스노우볼 속 메시지들 비공개 여부' }) - readonly message_private: boolean; + readonly is_message_private: boolean; } diff --git a/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts b/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts index d1519d2..a58c058 100644 --- a/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts @@ -13,5 +13,5 @@ export class ReqUpdateSnowballDto { type: Boolean, description: '스노우볼 속 메시지들 비공개 여부' }) - readonly message_private: boolean; + readonly is_message_private: boolean; } diff --git a/back/src/modules/snowball/dto/response/res-update-snowball.dto.ts b/back/src/modules/snowball/dto/response/res-update-snowball.dto.ts index d5decdd..b60be81 100644 --- a/back/src/modules/snowball/dto/response/res-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/response/res-update-snowball.dto.ts @@ -15,5 +15,5 @@ export class ResUpdateSnowballDto { type: Boolean, description: '변경된 스노우볼 속 메시지들 비공개 여부' }) - readonly message_private: boolean; + readonly is_message_private: boolean; } diff --git a/back/src/modules/snowball/dto/snowball.dto.ts b/back/src/modules/snowball/dto/snowball.dto.ts index f520bfd..71b0b0c 100644 --- a/back/src/modules/snowball/dto/snowball.dto.ts +++ b/back/src/modules/snowball/dto/snowball.dto.ts @@ -33,7 +33,7 @@ export class SnowballDto { type: Boolean, description: '스노우볼 속 메시지들 비공개 여부' }) - readonly message_private: boolean; + readonly is_message_private: boolean; @IsNotEmpty() @ValidateNested({ each: true }) diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index e738994..b3cc45c 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -26,7 +26,7 @@ export class SnowballService { const snowball = this.snowballRepository.create({ user_id: createSnowballDto.user_id, title: createSnowballDto.title, - message_private: createSnowballDto.message_private ? new Date() : null + message_private: createSnowballDto.is_message_private ? new Date() : null }); const savedSnowball = await this.snowballRepository.save(snowball); @@ -39,7 +39,7 @@ export class SnowballService { id: savedSnowball.id, uuid: savedSnowball.snowball_uuid, title: savedSnowball.title, - message_private: savedSnowball.message_private === null ? false : true, + is_message_private: savedSnowball.message_private === null ? false : true, deco_list: decoList, message_list: [] }; @@ -91,14 +91,14 @@ export class SnowballService { updateSnowballDto: ReqUpdateSnowballDto, snowball_id: number ): Promise { - const { title, message_private } = updateSnowballDto; + const { title, is_message_private } = updateSnowballDto; const updateResult = await this.snowballRepository .createQueryBuilder() .update(SnowballEntity) .set({ title, - message_private: message_private ? new Date() : null + message_private: is_message_private ? new Date() : null }) .where('id = :id', { id: snowball_id }) .execute(); @@ -111,7 +111,7 @@ export class SnowballService { const resUpdateSnowballDto: ResUpdateSnowballDto = { snowball_id, title, - message_private + is_message_private }; return resUpdateSnowballDto; @@ -133,7 +133,7 @@ export class SnowballService { id: snowball.id, uuid: snowball.snowball_uuid, title: snowball.title, - message_private: snowball.message_private ? true : false, + is_message_private: snowball.message_private ? true : false, deco_list: snowball.decorations, message_list: snowball.messages.map(message => ({ id: message.id, From 51dda77e18206bda535b410ce46eca629656598b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Thu, 23 Nov 2023 04:13:20 +0900 Subject: [PATCH 082/185] =?UTF-8?q?feat:=20swagger=20oauth2.0=20&=20jwt=20?= =?UTF-8?q?=ED=86=A0=ED=81=B0=20=ED=97=A4=EB=8D=94=20=EC=9D=B8=EC=A6=9D=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/package-lock.json | 55 +++++++++++++++++++ back/package.json | 1 + back/src/modules/auth/auth.controller.ts | 8 +-- back/src/modules/auth/auth.guard.ts | 2 +- back/src/modules/auth/auth.module.ts | 19 +++++-- .../src/modules/message/message.controller.ts | 10 +++- .../modules/snowball/snowball.controller.ts | 9 ++- back/src/modules/snowball/snowball.module.ts | 9 ++- back/src/util/swagger.ts | 13 ++++- 9 files changed, 111 insertions(+), 15 deletions(-) diff --git a/back/package-lock.json b/back/package-lock.json index 7a694ab..2f5aee5 100644 --- a/back/package-lock.json +++ b/back/package-lock.json @@ -12,6 +12,7 @@ "@nestjs/class-transformer": "^0.4.0", "@nestjs/class-validator": "^0.13.4", "@nestjs/common": "^10.0.0", + "@nestjs/config": "^3.1.1", "@nestjs/core": "^10.0.0", "@nestjs/jwt": "^10.2.0", "@nestjs/passport": "^10.0.2", @@ -1731,6 +1732,29 @@ } } }, + "node_modules/@nestjs/config": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-3.1.1.tgz", + "integrity": "sha512-qu5QlNiJdqQtOsnB6lx4JCXPQ96jkKUsOGd+JXfXwqJqZcOSAq6heNFg0opW4pq4J/VZoNwoo87TNnx9wthnqQ==", + "dependencies": { + "dotenv": "16.3.1", + "dotenv-expand": "10.0.0", + "lodash": "4.17.21", + "uuid": "9.0.0" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "reflect-metadata": "^0.1.13" + } + }, + "node_modules/@nestjs/config/node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@nestjs/core": { "version": "10.2.8", "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.2.8.tgz", @@ -4494,6 +4518,14 @@ "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, + "node_modules/dotenv-expand": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", + "engines": { + "node": ">=12" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -12093,6 +12125,24 @@ "uid": "2.0.2" } }, + "@nestjs/config": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-3.1.1.tgz", + "integrity": "sha512-qu5QlNiJdqQtOsnB6lx4JCXPQ96jkKUsOGd+JXfXwqJqZcOSAq6heNFg0opW4pq4J/VZoNwoo87TNnx9wthnqQ==", + "requires": { + "dotenv": "16.3.1", + "dotenv-expand": "10.0.0", + "lodash": "4.17.21", + "uuid": "9.0.0" + }, + "dependencies": { + "uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" + } + } + }, "@nestjs/core": { "version": "10.2.8", "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.2.8.tgz", @@ -14125,6 +14175,11 @@ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==" }, + "dotenv-expand": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==" + }, "eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", diff --git a/back/package.json b/back/package.json index 86372b9..f9f4693 100644 --- a/back/package.json +++ b/back/package.json @@ -23,6 +23,7 @@ "@nestjs/class-transformer": "^0.4.0", "@nestjs/class-validator": "^0.13.4", "@nestjs/common": "^10.0.0", + "@nestjs/config": "^3.1.1", "@nestjs/core": "^10.0.0", "@nestjs/jwt": "^10.2.0", "@nestjs/passport": "^10.0.2", diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index 1f49869..ce20fa7 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -37,8 +37,8 @@ export class AuthController { description: 'Internal Server Error' }) async googleLoginCallback(@Req() req): Promise { - const profile: string = req.user.profile; - const result = this.authService.createInfo(profile); + const userInfo = req.user; + const result = this.authService.createInfo(userInfo); return result; } @@ -71,8 +71,8 @@ export class AuthController { description: 'Internal Server Error' }) async naverLoginCallBack(@Req() req): Promise { - const profile: string = req.user.profile; - const result = this.authService.createInfo(profile); + const userInfo = req.user; + const result = this.authService.createInfo(userInfo); return result; } diff --git a/back/src/modules/auth/auth.guard.ts b/back/src/modules/auth/auth.guard.ts index 48ba6a1..bc46302 100644 --- a/back/src/modules/auth/auth.guard.ts +++ b/back/src/modules/auth/auth.guard.ts @@ -32,6 +32,6 @@ export class JWTGuard implements CanActivate { private extractTokenFromHeader(@Req() req: Request): string | undefined { const [type, token] = req.headers.authorization?.split(' ') ?? []; - return type === 'Bearer' ? token : null; + return type === 'Bearer' ? token : undefined; } } diff --git a/back/src/modules/auth/auth.module.ts b/back/src/modules/auth/auth.module.ts index e1c6f62..ad532f2 100644 --- a/back/src/modules/auth/auth.module.ts +++ b/back/src/modules/auth/auth.module.ts @@ -11,6 +11,9 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { SnowballEntity } from '../snowball/entity/snowball.entity'; import { UserEntity } from './entity/user.entity'; import { SnowballDecorationEntity } from '../snowball/entity/snowball-decoration.entity'; +import { JWTGuard } from './auth.guard'; +import { ConfigService } from '@nestjs/config'; +import { ConfigModule } from '@nestjs/config'; @Module({ imports: [ @@ -20,9 +23,13 @@ import { SnowballDecorationEntity } from '../snowball/entity/snowball-decoration SnowballDecorationEntity ]), PassportModule, - JwtModule.register({ - secret: process.env.JWT_SECRET, - signOptions: { expiresIn: '300s' } + ConfigModule.forRoot({ isGlobal: true }), + JwtModule.registerAsync({ + inject: [ConfigService], + useFactory: (config: ConfigService) => ({ + secret: config.get('JWT_SECRET'), + signOptions: { expiresIn: '300s' } + }) }) ], providers: [ @@ -30,8 +37,10 @@ import { SnowballDecorationEntity } from '../snowball/entity/snowball-decoration NaverAuthStrategy, KakaoAuthStrategy, AuthService, - SnowballService + SnowballService, + JWTGuard ], - controllers: [AuthController] + controllers: [AuthController], + exports: [JWTGuard] }) export class AuthModule {} diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 163981e..0a8fdd7 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -10,7 +10,13 @@ import { import { MessageService } from './message.service'; import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; import { ReqDeleteMessageDto } from './dto/request/req-delete-message.dto'; -import { ApiBody, ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; +import { + ApiBody, + ApiTags, + ApiOperation, + ApiResponse, + ApiBearerAuth +} from '@nestjs/swagger'; import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; import { MessageDto } from './dto/message.dto'; @@ -46,6 +52,7 @@ export class MessageController { return resCreateMessage; } + @ApiBearerAuth('jwt-token') @Delete(':message_id') @HttpCode(204) @ApiOperation({ @@ -61,6 +68,7 @@ export class MessageController { await this.messageService.deleteMessage(deleteMessageDto); } + @ApiBearerAuth('jwt-token') @Get('/:user_id') @HttpCode(200) @ApiOperation({ diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index 14d448c..fe8713a 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -5,7 +5,8 @@ import { Body, Param, Get, - HttpCode + HttpCode, + UseGuards } from '@nestjs/common'; import { SnowballService } from './snowball.service'; import { @@ -13,7 +14,8 @@ import { ApiTags, ApiOperation, ApiCreatedResponse, - ApiResponse + ApiResponse, + ApiBearerAuth } from '@nestjs/swagger'; import { ReqCreateSnowballDto } from './dto/request/req-create-snowball.dto'; import { ReqUpdateSnowballDto } from './dto/request/req-update-snowball.dto'; @@ -21,8 +23,11 @@ import { SnowballDto } from './dto/snowball.dto'; import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; import { ReqUpdateSnowballDecoDto } from './dto/request/req-update-decoration.dto'; import { ResUpdateSnowballDecoDto } from './dto/response/res-update-decoration.dto'; +import { JWTGuard } from '../auth/auth.guard'; @ApiTags('Snowball API') +@UseGuards(JWTGuard) +@ApiBearerAuth('jwt-token') @Controller('snowball') export class SnowballController { constructor(private readonly snowballService: SnowballService) {} diff --git a/back/src/modules/snowball/snowball.module.ts b/back/src/modules/snowball/snowball.module.ts index e8441ea..8ddb08b 100644 --- a/back/src/modules/snowball/snowball.module.ts +++ b/back/src/modules/snowball/snowball.module.ts @@ -6,6 +6,8 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { SnowballEntity } from './entity/snowball.entity'; import { MessageEntity } from '../message/entity/message.entity'; import { SnowballDecorationEntity } from './entity/snowball-decoration.entity'; +import { AuthModule } from '../auth/auth.module'; +import { JwtModule } from '@nestjs/jwt'; @Module({ imports: [ @@ -14,7 +16,12 @@ import { SnowballDecorationEntity } from './entity/snowball-decoration.entity'; MessageEntity, SnowballDecorationEntity ]), - MessageModule + JwtModule.register({ + secret: process.env.JWT_SECRET, + signOptions: { expiresIn: '300s' } + }), + MessageModule, + AuthModule ], controllers: [SnowballController], providers: [SnowballService] diff --git a/back/src/util/swagger.ts b/back/src/util/swagger.ts index a9cd949..876e365 100644 --- a/back/src/util/swagger.ts +++ b/back/src/util/swagger.ts @@ -17,6 +17,17 @@ export function setupSwagger(app: INestApplication): void { .setDescription('The SSOCK API description') .setVersion('1.0') .addTag('ssock') + .addOAuth2({ + type: 'oauth2', + flows: { + authorizationCode: { + authorizationUrl: 'http://www.mysnowball.kr/auth/google', + scopes: { + profile: 'profile' + } + } + } + }) .addBearerAuth( { type: 'http', @@ -25,7 +36,7 @@ export function setupSwagger(app: INestApplication): void { name: 'JWT', in: 'header' }, - 'token' + 'jwt-token' ) .build(); const document = SwaggerModule.createDocument(app, config); From 6ddd452ed17534128b4a036c89f22aa5a4442099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Thu, 23 Nov 2023 04:15:31 +0900 Subject: [PATCH 083/185] =?UTF-8?q?feat:=20message=EB=AA=A8=EB=93=88?= =?UTF-8?q?=EC=97=90=EB=8F=84=20jwt=20guard=20=EB=93=B1=EB=A1=9D!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.controller.ts | 6 +++++- back/src/modules/message/message.module.ts | 9 ++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 0a8fdd7..305534e 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -5,7 +5,8 @@ import { Delete, Body, Param, - HttpCode + HttpCode, + UseGuards } from '@nestjs/common'; import { MessageService } from './message.service'; import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; @@ -19,6 +20,7 @@ import { } from '@nestjs/swagger'; import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; import { MessageDto } from './dto/message.dto'; +import { JWTGuard } from '../auth/auth.guard'; @ApiTags('Message API') @Controller('message') @@ -52,6 +54,7 @@ export class MessageController { return resCreateMessage; } + @UseGuards(JWTGuard) @ApiBearerAuth('jwt-token') @Delete(':message_id') @HttpCode(204) @@ -68,6 +71,7 @@ export class MessageController { await this.messageService.deleteMessage(deleteMessageDto); } + @UseGuards(JWTGuard) @ApiBearerAuth('jwt-token') @Get('/:user_id') @HttpCode(200) diff --git a/back/src/modules/message/message.module.ts b/back/src/modules/message/message.module.ts index c0f2df8..01fb8e2 100644 --- a/back/src/modules/message/message.module.ts +++ b/back/src/modules/message/message.module.ts @@ -5,9 +5,16 @@ import { MessageService } from './message.service'; import { MessageEntity } from './entity/message.entity'; import { UserEntity } from '../auth/entity/user.entity'; import { SnowballEntity } from '../snowball/entity/snowball.entity'; +import { AuthModule } from '../auth/auth.module'; +import { JwtModule } from '@nestjs/jwt'; @Module({ imports: [ - TypeOrmModule.forFeature([UserEntity, SnowballEntity, MessageEntity]) + TypeOrmModule.forFeature([UserEntity, SnowballEntity, MessageEntity]), + JwtModule.register({ + secret: process.env.JWT_SECRET, + signOptions: { expiresIn: '300s' } + }), + AuthModule ], controllers: [MessageController], providers: [MessageService] From 5785c084ef47ed40c0496dac60359537d761cf40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Thu, 23 Nov 2023 04:25:45 +0900 Subject: [PATCH 084/185] =?UTF-8?q?fix:=20configMoudle=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/app.module.ts | 8 +++++++- back/src/modules/auth/auth.module.ts | 1 - 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/back/src/app.module.ts b/back/src/app.module.ts index a72e16d..cfe1e1a 100644 --- a/back/src/app.module.ts +++ b/back/src/app.module.ts @@ -5,9 +5,15 @@ import { AppService } from './app.service'; import { AuthModule } from './modules/auth/auth.module'; import { SnowballModule } from './modules/snowball/snowball.module'; import typeOrmConfig from './config/ormconfig'; +import { ConfigModule } from '@nestjs/config'; @Module({ - imports: [TypeOrmModule.forRoot(typeOrmConfig), AuthModule, SnowballModule], + imports: [ + TypeOrmModule.forRoot(typeOrmConfig), + ConfigModule.forRoot({ isGlobal: true }), + AuthModule, + SnowballModule + ], controllers: [AppController], providers: [AppService] }) diff --git a/back/src/modules/auth/auth.module.ts b/back/src/modules/auth/auth.module.ts index ad532f2..92422bd 100644 --- a/back/src/modules/auth/auth.module.ts +++ b/back/src/modules/auth/auth.module.ts @@ -23,7 +23,6 @@ import { ConfigModule } from '@nestjs/config'; SnowballDecorationEntity ]), PassportModule, - ConfigModule.forRoot({ isGlobal: true }), JwtModule.registerAsync({ inject: [ConfigService], useFactory: (config: ConfigService) => ({ From ac2b694af6b9d094b2d7d9d4a9ca36ce6260d43b Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 23 Nov 2023 11:01:30 +0900 Subject: [PATCH 085/185] =?UTF-8?q?fix:=20JWTModule=20=EA=B8=80=EB=A1=9C?= =?UTF-8?q?=EB=B2=8C=EB=A1=9C=20=EC=93=B8=EC=88=98=20=EC=9E=88=EA=B2=8C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'global' flag를 true로 바꾸어서 다른 모듈에서 따로 import 할 필요없게 만들어 주었다 --- back/src/modules/auth/auth.module.ts | 1 + back/src/modules/message/message.module.ts | 5 ----- back/src/modules/snowball/snowball.module.ts | 5 ----- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/back/src/modules/auth/auth.module.ts b/back/src/modules/auth/auth.module.ts index 92422bd..9b2b4c6 100644 --- a/back/src/modules/auth/auth.module.ts +++ b/back/src/modules/auth/auth.module.ts @@ -24,6 +24,7 @@ import { ConfigModule } from '@nestjs/config'; ]), PassportModule, JwtModule.registerAsync({ + global: true, inject: [ConfigService], useFactory: (config: ConfigService) => ({ secret: config.get('JWT_SECRET'), diff --git a/back/src/modules/message/message.module.ts b/back/src/modules/message/message.module.ts index 01fb8e2..dd3c0bb 100644 --- a/back/src/modules/message/message.module.ts +++ b/back/src/modules/message/message.module.ts @@ -6,14 +6,9 @@ import { MessageEntity } from './entity/message.entity'; import { UserEntity } from '../auth/entity/user.entity'; import { SnowballEntity } from '../snowball/entity/snowball.entity'; import { AuthModule } from '../auth/auth.module'; -import { JwtModule } from '@nestjs/jwt'; @Module({ imports: [ TypeOrmModule.forFeature([UserEntity, SnowballEntity, MessageEntity]), - JwtModule.register({ - secret: process.env.JWT_SECRET, - signOptions: { expiresIn: '300s' } - }), AuthModule ], controllers: [MessageController], diff --git a/back/src/modules/snowball/snowball.module.ts b/back/src/modules/snowball/snowball.module.ts index 8ddb08b..04dd4c6 100644 --- a/back/src/modules/snowball/snowball.module.ts +++ b/back/src/modules/snowball/snowball.module.ts @@ -7,7 +7,6 @@ import { SnowballEntity } from './entity/snowball.entity'; import { MessageEntity } from '../message/entity/message.entity'; import { SnowballDecorationEntity } from './entity/snowball-decoration.entity'; import { AuthModule } from '../auth/auth.module'; -import { JwtModule } from '@nestjs/jwt'; @Module({ imports: [ @@ -16,10 +15,6 @@ import { JwtModule } from '@nestjs/jwt'; MessageEntity, SnowballDecorationEntity ]), - JwtModule.register({ - secret: process.env.JWT_SECRET, - signOptions: { expiresIn: '300s' } - }), MessageModule, AuthModule ], From 5501a1956f09529d1dd6195bd5911a8ef2742615 Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 23 Nov 2023 13:44:06 +0900 Subject: [PATCH 086/185] =?UTF-8?q?feat:=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EC=98=A4=ED=94=88=20=ED=91=9C=EC=8B=9C=20API=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PUT /message/open/3 이런 식으로 메시지를 오픈했다는 표시해줄 수 있습니다. --- .../src/modules/message/message.controller.ts | 39 ++++++++++++++++++- back/src/modules/message/message.service.ts | 33 +++++++++++++++- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 305534e..b2e0307 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -6,7 +6,8 @@ import { Body, Param, HttpCode, - UseGuards + UseGuards, + Put } from '@nestjs/common'; import { MessageService } from './message.service'; import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; @@ -16,7 +17,11 @@ import { ApiTags, ApiOperation, ApiResponse, - ApiBearerAuth + ApiBearerAuth, + ApiNotFoundResponse, + ApiConflictResponse, + ApiBadRequestResponse, + ApiInternalServerErrorResponse } from '@nestjs/swagger'; import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; import { MessageDto } from './dto/message.dto'; @@ -93,4 +98,34 @@ export class MessageController { const messages = await this.messageService.getAllMessages(user_id); return messages; } + + @UseGuards(JWTGuard) + @ApiBearerAuth('jwt-token') + @Put('/open/:message_id') + @HttpCode(200) + @ApiOperation({ + summary: '메세지 오픈 처리', + description: '메시지를 오픈 처리합니다.' + }) + @ApiResponse({ + status: 200, + type: MessageDto + }) + @ApiBadRequestResponse({ + description: '잘못된 요청입니다.' + }) + @ApiNotFoundResponse({ + description: '해당 메시지가 존재하지 않습니다.' + }) + @ApiConflictResponse({ + description: '이미 오픈된 메시지입니다.' + }) + @ApiInternalServerErrorResponse({ + description: '서버측 오류' + }) + async openMessage( + @Param('message_id') message_id: number + ): Promise { + return await this.messageService.openMessage(message_id); + } } diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index e294c57..490bc31 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -1,4 +1,9 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; +import { + ConflictException, + Injectable, + InternalServerErrorException, + NotFoundException +} from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; @@ -84,4 +89,30 @@ export class MessageService { }); return messagesDto; } + + async openMessage(message_id: number): Promise { + try { + const message = await this.messageRepository.findOne({ + where: { id: message_id } + }); + if (!message) { + throw new NotFoundException( + `${message_id} 메시지를 찾을 수 없었습니다.` + ); + } + if (message.opened !== null) { + throw new ConflictException( + `${message_id} 메시지는 이미 열려있습니다.` + ); + } + const date = new Date(); + await this.messageRepository.update(message_id, { opened: date }); + return { + ...message, + opened: date + }; + } catch (err) { + throw new InternalServerErrorException('서버측 오류'); + } + } } From ed1eb198008ff8ad5be4efd97eb1d1bfaf0ec20d Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 23 Nov 2023 14:18:09 +0900 Subject: [PATCH 087/185] =?UTF-8?q?feat:=20user=5Fid=EB=8A=94=20JWT?= =?UTF-8?q?=ED=86=A0=ED=81=B0=EC=97=90=EC=84=9C=20=EA=B0=80=EC=A0=B8?= =?UTF-8?q?=EC=98=A4=EA=B8=B0=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JWTGuard가 Request.user에 userid를 넣어줘서 컨트롤러에서 @Req() req: any로 request를 파라미터 받고 req.user로 user id 사용 가능 --- back/src/modules/message/message.controller.ts | 16 ++++++++-------- back/src/modules/snowball/snowball.controller.ts | 9 +++++++-- back/src/modules/snowball/snowball.service.ts | 3 ++- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index b2e0307..42f9685 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -7,7 +7,8 @@ import { Param, HttpCode, UseGuards, - Put + Put, + Req } from '@nestjs/common'; import { MessageService } from './message.service'; import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; @@ -78,24 +79,23 @@ export class MessageController { @UseGuards(JWTGuard) @ApiBearerAuth('jwt-token') - @Get('/:user_id') + @Get('/') @HttpCode(200) @ApiOperation({ summary: '메세지 조회 API', - description: '모든 메세지를 조회합니다' + description: + '모든 메세지를 조회합니다. JWT 토큰안에 user_id를 이용해 조회합니다.' }) @ApiResponse({ status: 200, - type: MessageDto + type: [MessageDto] }) @ApiResponse({ status: 500, description: 'Find Fail' }) - async getAllMessages( - @Param('user_id') user_id: number - ): Promise { - const messages = await this.messageService.getAllMessages(user_id); + async getAllMessages(@Req() req: any): Promise { + const messages = await this.messageService.getAllMessages(req.user); return messages; } diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index fe8713a..58885d4 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -6,7 +6,8 @@ import { Param, Get, HttpCode, - UseGuards + UseGuards, + Req } from '@nestjs/common'; import { SnowballService } from './snowball.service'; import { @@ -44,9 +45,13 @@ export class SnowballController { }) @ApiBody({ type: ReqCreateSnowballDto }) createSnowball( + @Req() req: any, @Body() createSnowballDto: ReqCreateSnowballDto ): Promise { - const snowball = this.snowballService.createSnowball(createSnowballDto); + const snowball = this.snowballService.createSnowball( + req.user, + createSnowballDto + ); return snowball; } diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index b3cc45c..98fce49 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -21,10 +21,11 @@ export class SnowballService { ) {} async createSnowball( + userid: number, createSnowballDto: ReqCreateSnowballDto ): Promise { const snowball = this.snowballRepository.create({ - user_id: createSnowballDto.user_id, + user_id: userid, title: createSnowballDto.title, message_private: createSnowballDto.is_message_private ? new Date() : null }); From 37ac0194cd73cf8eeec81716f93fff078047c34a Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 23 Nov 2023 14:29:46 +0900 Subject: [PATCH 088/185] =?UTF-8?q?feat:=20message=20=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=EC=97=90=20user=5Fid=20=EC=BB=AC=EB=9F=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/entity/user.entity.ts | 4 ++++ back/src/modules/message/entity/message.entity.ts | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/back/src/modules/auth/entity/user.entity.ts b/back/src/modules/auth/entity/user.entity.ts index e363b5d..fcbac72 100644 --- a/back/src/modules/auth/entity/user.entity.ts +++ b/back/src/modules/auth/entity/user.entity.ts @@ -6,6 +6,7 @@ import { CreateDateColumn } from 'typeorm'; import { SnowballEntity } from '../../snowball/entity/snowball.entity'; +import { MessageEntity } from 'src/modules/message/entity/message.entity'; @Entity({ name: 'user' }) export class UserEntity { @@ -26,4 +27,7 @@ export class UserEntity { @OneToMany(() => SnowballEntity, snowball => snowball.user) snowballs: SnowballEntity[]; + + @OneToMany(() => MessageEntity, message => message.user) + messages: MessageEntity[]; } diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 62a9f27..27df8ad 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -7,12 +7,16 @@ import { JoinColumn } from 'typeorm'; import { SnowballEntity } from 'src/modules/snowball/entity/snowball.entity'; +import { UserEntity } from 'src/modules/auth/entity/user.entity'; @Entity({ synchronize: true, name: 'message' }) export class MessageEntity { @PrimaryGeneratedColumn() id: number; + @Column() + user_id: number; + @Column() snowball_id: number; @@ -40,4 +44,8 @@ export class MessageEntity { @ManyToOne(() => SnowballEntity, snowball => snowball.messages) @JoinColumn({ name: 'snowball_id' }) snowball: SnowballEntity; + + @ManyToOne(() => UserEntity, user => user.messages) + @JoinColumn({ name: 'user_id' }) + user: UserEntity; } From 685fe8bca7a580d59223d8b596df9408443d929f Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 23 Nov 2023 14:53:56 +0900 Subject: [PATCH 089/185] =?UTF-8?q?feat:=20message=20=EC=86=8C=ED=94=84?= =?UTF-8?q?=ED=8A=B8=20=EB=94=9C=EB=A6=AC=ED=8A=B8=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/req-delete-message.dto.ts | 9 ------- .../modules/message/entity/message.entity.ts | 3 +++ .../src/modules/message/message.controller.ts | 23 +++++++++++----- back/src/modules/message/message.service.ts | 27 ++++++++++++++++--- 4 files changed, 43 insertions(+), 19 deletions(-) delete mode 100644 back/src/modules/message/dto/request/req-delete-message.dto.ts diff --git a/back/src/modules/message/dto/request/req-delete-message.dto.ts b/back/src/modules/message/dto/request/req-delete-message.dto.ts deleted file mode 100644 index 82f2662..0000000 --- a/back/src/modules/message/dto/request/req-delete-message.dto.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { IsNumber, IsNotEmpty } from '@nestjs/class-validator'; -import { ApiProperty } from '@nestjs/swagger'; - -export class ReqDeleteMessageDto { - @IsNumber() - @IsNotEmpty() - @ApiProperty({ type: Number, description: '메세지 id' }) - readonly message_id: number; -} diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 27df8ad..0a59dcf 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -35,6 +35,9 @@ export class MessageEntity { @Column({ length: 16 }) sender: string; + @Column({ type: 'boolean', default: false }) + is_deleted: boolean; + @CreateDateColumn({ nullable: true, default: null }) opened: Date | null; diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 42f9685..74370cb 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -12,7 +12,6 @@ import { } from '@nestjs/common'; import { MessageService } from './message.service'; import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; -import { ReqDeleteMessageDto } from './dto/request/req-delete-message.dto'; import { ApiBody, ApiTags, @@ -22,7 +21,9 @@ import { ApiNotFoundResponse, ApiConflictResponse, ApiBadRequestResponse, - ApiInternalServerErrorResponse + ApiInternalServerErrorResponse, + ApiGoneResponse, + ApiUnauthorizedResponse } from '@nestjs/swagger'; import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; import { MessageDto } from './dto/message.dto'; @@ -68,13 +69,21 @@ export class MessageController { summary: '메세지 삭제 API', description: '스노우볼에서 특정 메세지를 삭제합니다.' }) - @ApiResponse({ status: 204, description: 'No Content' }) @ApiResponse({ - status: 500, - description: 'Delete Fail' + status: 204, + description: '해당 메시지가 성공적으로 지워졌음' + }) + @ApiGoneResponse({ + description: '이미 삭제된 메시지입니다.' }) - async deleteMessage(@Param() deleteMessageDto: ReqDeleteMessageDto) { - await this.messageService.deleteMessage(deleteMessageDto); + @ApiUnauthorizedResponse({ + description: '로그인이 필요합니다.' + }) + async deleteMessage( + @Req() req: any, + @Param('message_id') message_id: number + ) { + await this.messageService.deleteMessage(req.user, message_id); } @UseGuards(JWTGuard) diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 490bc31..f4acaf5 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -1,5 +1,7 @@ import { ConflictException, + ForbiddenException, + GoneException, Injectable, InternalServerErrorException, NotFoundException @@ -7,7 +9,6 @@ import { import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; -import { ReqDeleteMessageDto } from './dto/request/req-delete-message.dto'; import { MessageEntity } from './entity/message.entity'; import { UserEntity } from '../auth/entity/user.entity'; import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; @@ -44,8 +45,28 @@ export class MessageService { return resCreateMessage; } - async deleteMessage(deleteMessageDto: ReqDeleteMessageDto): Promise { - await this.messageRepository.delete(deleteMessageDto.message_id); + async deleteMessage(user_id: number, message_id: number): Promise { + try { + const message = await this.messageRepository.findOne({ + where: { id: message_id } + }); + if (message.user_id !== user_id) { + throw new ForbiddenException( + `${message_id} 메시지는 해당 유저의 메시지가 아닙니다.` + ); + } + if (!message) { + throw new NotFoundException( + `${message_id} 메시지를 찾을 수 없었습니다.` + ); + } + if (message.is_deleted) { + throw new GoneException(`${message_id}는 이미 삭제된 메시지입니다.`); + } + await this.messageRepository.update(message_id, { is_deleted: true }); + } catch (err) { + throw new InternalServerErrorException('서버측 오류'); + } } async getAllMessages(user_id: number): Promise { From 2f7117b479d3cf859926e03b716bf49e939b96e6 Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 23 Nov 2023 15:10:03 +0900 Subject: [PATCH 090/185] =?UTF-8?q?feat:=20letter,=20decorationPrefix=20?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=B8=94=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/entity/letter.entity.ts | 11 +++++++++++ back/src/modules/message/entity/message.entity.ts | 6 ++++++ .../snowball/entity/decoration-prefix.entity.ts | 14 ++++++++++++++ .../snowball/entity/snowball-decoration.entity.ts | 8 ++++++++ 4 files changed, 39 insertions(+) create mode 100644 back/src/modules/message/entity/letter.entity.ts create mode 100644 back/src/modules/snowball/entity/decoration-prefix.entity.ts diff --git a/back/src/modules/message/entity/letter.entity.ts b/back/src/modules/message/entity/letter.entity.ts new file mode 100644 index 0000000..66c1ba3 --- /dev/null +++ b/back/src/modules/message/entity/letter.entity.ts @@ -0,0 +1,11 @@ +import { Entity, PrimaryGeneratedColumn, OneToMany } from 'typeorm'; +import { MessageEntity } from './message.entity'; + +@Entity() +export class LetterEntity { + @PrimaryGeneratedColumn() + id: number; + + @OneToMany(() => MessageEntity, message => message.letter_id) + messages: MessageEntity[]; +} diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 0a59dcf..15dcf37 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -8,6 +8,7 @@ import { } from 'typeorm'; import { SnowballEntity } from 'src/modules/snowball/entity/snowball.entity'; import { UserEntity } from 'src/modules/auth/entity/user.entity'; +import { LetterEntity } from './letter.entity'; @Entity({ synchronize: true, name: 'message' }) export class MessageEntity { @@ -51,4 +52,9 @@ export class MessageEntity { @ManyToOne(() => UserEntity, user => user.messages) @JoinColumn({ name: 'user_id' }) user: UserEntity; + + //many to one relation letter_id with id in LetterEntity in letter.entity.ts + @ManyToOne(() => LetterEntity, letter => letter.messages) + @JoinColumn({ name: 'letter_id' }) + letter: LetterEntity; } diff --git a/back/src/modules/snowball/entity/decoration-prefix.entity.ts b/back/src/modules/snowball/entity/decoration-prefix.entity.ts new file mode 100644 index 0000000..c5126aa --- /dev/null +++ b/back/src/modules/snowball/entity/decoration-prefix.entity.ts @@ -0,0 +1,14 @@ +import { Entity, PrimaryGeneratedColumn, OneToMany } from 'typeorm'; +import { SnowballDecorationEntity } from './snowball-decoration.entity'; + +@Entity() +export class DecorationPrefixEntity { + @PrimaryGeneratedColumn() + id: number; + + @OneToMany( + () => SnowballDecorationEntity, + snowballDecoration => snowballDecoration.decoration_id + ) + decorations: SnowballDecorationEntity[]; +} diff --git a/back/src/modules/snowball/entity/snowball-decoration.entity.ts b/back/src/modules/snowball/entity/snowball-decoration.entity.ts index 9b25028..52c4d44 100644 --- a/back/src/modules/snowball/entity/snowball-decoration.entity.ts +++ b/back/src/modules/snowball/entity/snowball-decoration.entity.ts @@ -6,6 +6,7 @@ import { JoinColumn } from 'typeorm'; import { SnowballEntity } from './snowball.entity'; +import { DecorationPrefixEntity } from './decoration-prefix.entity'; @Entity({ name: 'snowball_decoration' }) export class SnowballDecorationEntity { @@ -27,4 +28,11 @@ export class SnowballDecorationEntity { @ManyToOne(() => SnowballEntity, snowball => snowball.decorations) @JoinColumn({ name: 'snowball_id' }) snowball: SnowballEntity; + + @ManyToOne( + () => DecorationPrefixEntity, + decorationPrefix => decorationPrefix.decorations + ) + @JoinColumn({ name: 'decoration_id' }) + decorationPrefix: DecorationPrefixEntity; } From 278356616f1e2e19f0734ebdafa5c14322b133b4 Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 23 Nov 2023 15:18:43 +0900 Subject: [PATCH 091/185] =?UTF-8?q?fix:=20letter=5Fprefix,=20decoration=5F?= =?UTF-8?q?prefix=20=ED=85=8C=EC=9D=B4=EB=B8=94=EB=A1=9C=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EB=90=98=EA=B2=8C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/entity/letter.entity.ts | 2 +- back/src/modules/snowball/entity/decoration-prefix.entity.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/back/src/modules/message/entity/letter.entity.ts b/back/src/modules/message/entity/letter.entity.ts index 66c1ba3..26ae4bb 100644 --- a/back/src/modules/message/entity/letter.entity.ts +++ b/back/src/modules/message/entity/letter.entity.ts @@ -1,7 +1,7 @@ import { Entity, PrimaryGeneratedColumn, OneToMany } from 'typeorm'; import { MessageEntity } from './message.entity'; -@Entity() +@Entity({ name: 'letter_prefix' }) export class LetterEntity { @PrimaryGeneratedColumn() id: number; diff --git a/back/src/modules/snowball/entity/decoration-prefix.entity.ts b/back/src/modules/snowball/entity/decoration-prefix.entity.ts index c5126aa..e761fd9 100644 --- a/back/src/modules/snowball/entity/decoration-prefix.entity.ts +++ b/back/src/modules/snowball/entity/decoration-prefix.entity.ts @@ -1,7 +1,7 @@ import { Entity, PrimaryGeneratedColumn, OneToMany } from 'typeorm'; import { SnowballDecorationEntity } from './snowball-decoration.entity'; -@Entity() +@Entity({ name: 'decoration_prefix' }) export class DecorationPrefixEntity { @PrimaryGeneratedColumn() id: number; From 30b1e3cc0aeaa0b2a7f6a9cc4d3ed94bb6d4f275 Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 23 Nov 2023 16:00:01 +0900 Subject: [PATCH 092/185] =?UTF-8?q?fix:=20/message/:message=5Fid/open=20?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 74370cb..0f8c70c 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -110,7 +110,7 @@ export class MessageController { @UseGuards(JWTGuard) @ApiBearerAuth('jwt-token') - @Put('/open/:message_id') + @Put('/:message_id/open') @HttpCode(200) @ApiOperation({ summary: '메세지 오픈 처리', From 8f628fb916f2cfa7facf501ee11e902e2bdd2df5 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Thu, 23 Nov 2023 17:26:20 +0900 Subject: [PATCH 093/185] =?UTF-8?q?feat:=20api=20=EB=9D=BC=EC=9A=B0?= =?UTF-8?q?=ED=8A=B8=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/app.module.ts | 12 +++++++++++- back/src/main.ts | 1 + back/src/modules/auth/auth.module.ts | 13 +------------ back/src/modules/auth/auth.service.ts | 5 +++-- .../modules/auth/strategy/google-auth.strategy.ts | 2 +- .../modules/auth/strategy/kakao-auth.strategy.ts | 2 +- .../modules/auth/strategy/naver-auth.strategy.ts | 2 +- back/src/util/swagger.ts | 4 ++-- 8 files changed, 21 insertions(+), 20 deletions(-) diff --git a/back/src/app.module.ts b/back/src/app.module.ts index cfe1e1a..0be1f26 100644 --- a/back/src/app.module.ts +++ b/back/src/app.module.ts @@ -6,13 +6,23 @@ import { AuthModule } from './modules/auth/auth.module'; import { SnowballModule } from './modules/snowball/snowball.module'; import typeOrmConfig from './config/ormconfig'; import { ConfigModule } from '@nestjs/config'; +import { ConfigService } from '@nestjs/config'; +import { JwtModule } from '@nestjs/jwt'; @Module({ imports: [ TypeOrmModule.forRoot(typeOrmConfig), ConfigModule.forRoot({ isGlobal: true }), AuthModule, - SnowballModule + SnowballModule, + JwtModule.registerAsync({ + global: true, + inject: [ConfigService], + useFactory: (config: ConfigService) => ({ + secret: config.get('JWT_SECRET'), + signOptions: { expiresIn: '300s' } + }) + }) ], controllers: [AppController], providers: [AppService] diff --git a/back/src/main.ts b/back/src/main.ts index deca767..553fc70 100644 --- a/back/src/main.ts +++ b/back/src/main.ts @@ -4,6 +4,7 @@ import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); + app.setGlobalPrefix('api') setupSwagger(app); await app.listen(3000); } diff --git a/back/src/modules/auth/auth.module.ts b/back/src/modules/auth/auth.module.ts index 9b2b4c6..5b8b37e 100644 --- a/back/src/modules/auth/auth.module.ts +++ b/back/src/modules/auth/auth.module.ts @@ -5,15 +5,12 @@ import { KakaoAuthStrategy } from './strategy/kakao-auth.strategy'; import { AuthController } from './auth.controller'; import { PassportModule } from '@nestjs/passport'; import { AuthService } from './auth.service'; -import { JwtModule } from '@nestjs/jwt'; import { SnowballService } from '../snowball/snowball.service'; import { TypeOrmModule } from '@nestjs/typeorm'; import { SnowballEntity } from '../snowball/entity/snowball.entity'; import { UserEntity } from './entity/user.entity'; import { SnowballDecorationEntity } from '../snowball/entity/snowball-decoration.entity'; import { JWTGuard } from './auth.guard'; -import { ConfigService } from '@nestjs/config'; -import { ConfigModule } from '@nestjs/config'; @Module({ imports: [ @@ -22,15 +19,7 @@ import { ConfigModule } from '@nestjs/config'; UserEntity, SnowballDecorationEntity ]), - PassportModule, - JwtModule.registerAsync({ - global: true, - inject: [ConfigService], - useFactory: (config: ConfigService) => ({ - secret: config.get('JWT_SECRET'), - signOptions: { expiresIn: '300s' } - }) - }) + PassportModule ], providers: [ GoogleAuthStrategy, diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index 7d4a33d..bd143cb 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -18,7 +18,7 @@ export class AuthService { async createInfo(user: any): Promise { const jwt_token = this.generateJwtToken(user); - const userDto: UserDto = await this.createUserDto(); + const userDto: UserDto = await this.createUserDto(user); const mainSnowballDto: SnowballDto = await this.snowballService.getSnowball(1); @@ -31,8 +31,9 @@ export class AuthService { return resInfoDto; } - async createUserDto(): Promise { + async createUserDto(user:any): Promise { // To Do : 쿼리짜기.. + console.log(user); return { id: 1, name: '김찬우', diff --git a/back/src/modules/auth/strategy/google-auth.strategy.ts b/back/src/modules/auth/strategy/google-auth.strategy.ts index 089d943..47a9fcf 100644 --- a/back/src/modules/auth/strategy/google-auth.strategy.ts +++ b/back/src/modules/auth/strategy/google-auth.strategy.ts @@ -8,7 +8,7 @@ export class GoogleAuthStrategy extends PassportStrategy(Strategy, 'google') { super({ clientID: `${process.env.GOOGLE_CLIENT_ID}`, clientSecret: `${process.env.GOOGLE_SECRET}`, - callbackURL: 'http://localhost:3000/auth/google/redirect', + callbackURL: 'http://localhost:3000/api/auth/google/redirect', scope: ['profile'] }); } diff --git a/back/src/modules/auth/strategy/kakao-auth.strategy.ts b/back/src/modules/auth/strategy/kakao-auth.strategy.ts index 8a2f043..c6c7f43 100644 --- a/back/src/modules/auth/strategy/kakao-auth.strategy.ts +++ b/back/src/modules/auth/strategy/kakao-auth.strategy.ts @@ -8,7 +8,7 @@ export class KakaoAuthStrategy extends PassportStrategy(Strategy, 'kakao') { super({ clientID: `${process.env.KAKAO_CLIENT_ID}`, clientSecret: `${process.env.KAKAO_SECRET}`, - callbackURL: 'http://localhost:3000/auth/kakao/redirect', // redirect_uri + callbackURL: 'http://localhost:3000/api/auth/kakao/redirect', // redirect_uri passReqToCallback: false, scope: ['profile_nickname'] }); diff --git a/back/src/modules/auth/strategy/naver-auth.strategy.ts b/back/src/modules/auth/strategy/naver-auth.strategy.ts index be56d04..d72d9f1 100644 --- a/back/src/modules/auth/strategy/naver-auth.strategy.ts +++ b/back/src/modules/auth/strategy/naver-auth.strategy.ts @@ -8,7 +8,7 @@ export class NaverAuthStrategy extends PassportStrategy(Strategy, 'naver') { super({ clientID: `${process.env.NAVER_CLIENT_ID}`, clientSecret: `${process.env.NAVER_SECRET}`, - callbackURL: 'http://localhost:3000/auth/naver/redirect', // redirect_uri + callbackURL: 'http://localhost:3000/api/auth/naver/redirect', // redirect_uri passReqToCallback: false, scope: ['profile'] }); diff --git a/back/src/util/swagger.ts b/back/src/util/swagger.ts index 876e365..db01307 100644 --- a/back/src/util/swagger.ts +++ b/back/src/util/swagger.ts @@ -4,7 +4,7 @@ import * as expressBasicAuth from 'express-basic-auth'; export function setupSwagger(app: INestApplication): void { app.use( - ['/api'], + ['/docs'], expressBasicAuth({ challenge: true, users: { @@ -40,7 +40,7 @@ export function setupSwagger(app: INestApplication): void { ) .build(); const document = SwaggerModule.createDocument(app, config); - SwaggerModule.setup('api', app, document, { + SwaggerModule.setup('docs', app, document, { swaggerOptions: { persistAuthorization: true } From 944b74bd1079bfab707f0b5c18b2242b5258caa5 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Thu, 23 Nov 2023 17:27:25 +0900 Subject: [PATCH 094/185] =?UTF-8?q?fix:=20redirect=20url=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/strategy/google-auth.strategy.ts | 2 +- back/src/modules/auth/strategy/kakao-auth.strategy.ts | 2 +- back/src/modules/auth/strategy/naver-auth.strategy.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/back/src/modules/auth/strategy/google-auth.strategy.ts b/back/src/modules/auth/strategy/google-auth.strategy.ts index 47a9fcf..9d3f598 100644 --- a/back/src/modules/auth/strategy/google-auth.strategy.ts +++ b/back/src/modules/auth/strategy/google-auth.strategy.ts @@ -8,7 +8,7 @@ export class GoogleAuthStrategy extends PassportStrategy(Strategy, 'google') { super({ clientID: `${process.env.GOOGLE_CLIENT_ID}`, clientSecret: `${process.env.GOOGLE_SECRET}`, - callbackURL: 'http://localhost:3000/api/auth/google/redirect', + callbackURL: 'http://www.mysnowball.kr/api/auth/google/redirect', scope: ['profile'] }); } diff --git a/back/src/modules/auth/strategy/kakao-auth.strategy.ts b/back/src/modules/auth/strategy/kakao-auth.strategy.ts index c6c7f43..1b7e0da 100644 --- a/back/src/modules/auth/strategy/kakao-auth.strategy.ts +++ b/back/src/modules/auth/strategy/kakao-auth.strategy.ts @@ -8,7 +8,7 @@ export class KakaoAuthStrategy extends PassportStrategy(Strategy, 'kakao') { super({ clientID: `${process.env.KAKAO_CLIENT_ID}`, clientSecret: `${process.env.KAKAO_SECRET}`, - callbackURL: 'http://localhost:3000/api/auth/kakao/redirect', // redirect_uri + callbackURL: 'http://www.mysnowball.kr/api/auth/kakao/redirect', passReqToCallback: false, scope: ['profile_nickname'] }); diff --git a/back/src/modules/auth/strategy/naver-auth.strategy.ts b/back/src/modules/auth/strategy/naver-auth.strategy.ts index d72d9f1..2bf51f3 100644 --- a/back/src/modules/auth/strategy/naver-auth.strategy.ts +++ b/back/src/modules/auth/strategy/naver-auth.strategy.ts @@ -8,7 +8,7 @@ export class NaverAuthStrategy extends PassportStrategy(Strategy, 'naver') { super({ clientID: `${process.env.NAVER_CLIENT_ID}`, clientSecret: `${process.env.NAVER_SECRET}`, - callbackURL: 'http://localhost:3000/api/auth/naver/redirect', // redirect_uri + callbackURL: 'http://www.mysnowball.kr/api/auth/naver/redirect', // redirect_uri passReqToCallback: false, scope: ['profile'] }); From 54835bfc3c6d8f60193d59b7c961ce89c7b801c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Thu, 23 Nov 2023 17:33:57 +0900 Subject: [PATCH 095/185] Update swagger.ts --- back/src/util/swagger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/src/util/swagger.ts b/back/src/util/swagger.ts index db01307..c0a351f 100644 --- a/back/src/util/swagger.ts +++ b/back/src/util/swagger.ts @@ -21,7 +21,7 @@ export function setupSwagger(app: INestApplication): void { type: 'oauth2', flows: { authorizationCode: { - authorizationUrl: 'http://www.mysnowball.kr/auth/google', + authorizationUrl: 'http://www.mysnowball.kr/api/auth/google', scopes: { profile: 'profile' } From b4d442ec62a1b5e20ea37615e20ee476482900bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Fri, 24 Nov 2023 03:33:30 +0900 Subject: [PATCH 096/185] =?UTF-8?q?feat:=20createInfo=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.guard.ts | 3 +- back/src/modules/auth/auth.service.ts | 50 ++++++++++++++----- .../modules/auth/dto/response/res-info.dto.ts | 2 +- .../auth/strategy/google-auth.strategy.ts | 1 + .../auth/strategy/kakao-auth.strategy.ts | 1 + .../auth/strategy/naver-auth.strategy.ts | 3 +- back/src/modules/snowball/snowball.service.ts | 4 +- 7 files changed, 45 insertions(+), 19 deletions(-) diff --git a/back/src/modules/auth/auth.guard.ts b/back/src/modules/auth/auth.guard.ts index bc46302..037bb66 100644 --- a/back/src/modules/auth/auth.guard.ts +++ b/back/src/modules/auth/auth.guard.ts @@ -22,8 +22,7 @@ export class JWTGuard implements CanActivate { const payload = await this.jwtService.verify(token, { secret: process.env.JWT_SECRET }); - // route 핸들러에서 request.user로 사용할 수 있도록 넣어줌 - request['user'] = payload; + request['user'] = payload.userid; // 이거 oauth2.0 아이디라 pk로 바꿔야함 } catch { throw new UnauthorizedException(); } diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index bd143cb..64a9be5 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -7,11 +7,14 @@ import { SnowballService } from '../snowball/snowball.service'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { UserEntity } from './entity/user.entity'; +import { SnowballEntity } from '../snowball/entity/snowball.entity'; @Injectable() export class AuthService { constructor( @InjectRepository(UserEntity) private readonly UserRepository: Repository, + @InjectRepository(SnowballEntity) + private readonly SnowballRepository: Repository, private readonly jwtService: JwtService, private readonly snowballService: SnowballService ) {} @@ -31,25 +34,46 @@ export class AuthService { return resInfoDto; } - async createUserDto(user:any): Promise { - // To Do : 쿼리짜기.. - console.log(user); - return { - id: 1, - name: '김찬우', - auth_id: 'Oauth에서 주는 값', + async createUserDto(user: any): Promise { + const exisitingUser = await this.UserRepository.findOne({ + where: { user_id: user.id } + }); + + let userId; + if (exisitingUser) { + userId = exisitingUser.id; + + const snowballCount = await this.SnowballRepository.findAndCount({ + where: { user_id: userId } + }); + const snowballList = await this.SnowballRepository.find({ + where: { user_id: userId } + }); + console.log(snowballCount, snowballList); + } else { + const newUser: UserEntity = this.UserRepository.create({ + user_id: user.id, + username: user.name, + provider: user.provider, + created_at: new Date() + }); + + const saveduser = await this.UserRepository.insert(newUser); + userId = saveduser.identifiers.pop().id; + } + const userDto: UserDto = { + id: userId, + name: user.name, + auth_id: user.id, snowball_count: 3, - snowball_list: [ - { id: 1, uuid: '32413434-32a2-2342-3242-3g23-413oye3' }, - { id: 2, uuid: '32413434-32a2-2342-3242-3g23-413oye4' }, - { id: 3, uuid: '32413434-32a2-2342-3242-3g23-413oye5' } - ], + snowball_list: [], message_count: 123 }; + return userDto; } generateJwtToken(user: any): string { - const payload = { userid: user.id, username: user.username }; + const payload = { userid: user.id, username: user.name }; return this.jwtService.sign(payload); } } diff --git a/back/src/modules/auth/dto/response/res-info.dto.ts b/back/src/modules/auth/dto/response/res-info.dto.ts index 60a1b9a..e42e86f 100644 --- a/back/src/modules/auth/dto/response/res-info.dto.ts +++ b/back/src/modules/auth/dto/response/res-info.dto.ts @@ -24,5 +24,5 @@ export class ResInfoDto { type: SnowballDto, description: '메인 스노우볼 정보' }) - readonly main_snowball: SnowballDto; + readonly main_snowball: SnowballDto | null; } diff --git a/back/src/modules/auth/strategy/google-auth.strategy.ts b/back/src/modules/auth/strategy/google-auth.strategy.ts index 9d3f598..963477e 100644 --- a/back/src/modules/auth/strategy/google-auth.strategy.ts +++ b/back/src/modules/auth/strategy/google-auth.strategy.ts @@ -9,6 +9,7 @@ export class GoogleAuthStrategy extends PassportStrategy(Strategy, 'google') { clientID: `${process.env.GOOGLE_CLIENT_ID}`, clientSecret: `${process.env.GOOGLE_SECRET}`, callbackURL: 'http://www.mysnowball.kr/api/auth/google/redirect', + //callbackURL: 'http://localhost:3000/api/auth/google/redirect', scope: ['profile'] }); } diff --git a/back/src/modules/auth/strategy/kakao-auth.strategy.ts b/back/src/modules/auth/strategy/kakao-auth.strategy.ts index 1b7e0da..04c5783 100644 --- a/back/src/modules/auth/strategy/kakao-auth.strategy.ts +++ b/back/src/modules/auth/strategy/kakao-auth.strategy.ts @@ -9,6 +9,7 @@ export class KakaoAuthStrategy extends PassportStrategy(Strategy, 'kakao') { clientID: `${process.env.KAKAO_CLIENT_ID}`, clientSecret: `${process.env.KAKAO_SECRET}`, callbackURL: 'http://www.mysnowball.kr/api/auth/kakao/redirect', + //callbackURL: 'http://localhost:3000/api/auth/kakao/redirect', passReqToCallback: false, scope: ['profile_nickname'] }); diff --git a/back/src/modules/auth/strategy/naver-auth.strategy.ts b/back/src/modules/auth/strategy/naver-auth.strategy.ts index 2bf51f3..25fe47d 100644 --- a/back/src/modules/auth/strategy/naver-auth.strategy.ts +++ b/back/src/modules/auth/strategy/naver-auth.strategy.ts @@ -8,7 +8,8 @@ export class NaverAuthStrategy extends PassportStrategy(Strategy, 'naver') { super({ clientID: `${process.env.NAVER_CLIENT_ID}`, clientSecret: `${process.env.NAVER_SECRET}`, - callbackURL: 'http://www.mysnowball.kr/api/auth/naver/redirect', // redirect_uri + callbackURL: 'http://www.mysnowball.kr/api/auth/naver/redirect', + //callbackURL: 'http://localhost:3000/api/auth/naver/redirect', passReqToCallback: false, scope: ['profile'] }); diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 98fce49..2e15f70 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -118,7 +118,7 @@ export class SnowballService { return resUpdateSnowballDto; } - async getSnowball(snowball_id: number): Promise { + async getSnowball(snowball_id: number): Promise | null { const snowball = await this.snowballRepository.findOne({ where: { id: snowball_id }, relations: { @@ -127,7 +127,7 @@ export class SnowballService { } }); if (!snowball) { - throw new NotFoundException('스노우볼이 존재하지 않습니다.'); + return null; } const resSnowball: SnowballDto = { From 3bd996e346d5fdaa25f1ecd9987ea424130cfe38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Fri, 24 Nov 2023 06:13:08 +0900 Subject: [PATCH 097/185] =?UTF-8?q?feat:=20prefix=201:n=20=EA=B4=80?= =?UTF-8?q?=EA=B3=84=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/entity/letter.entity.ts | 6 +----- back/src/modules/message/entity/message.entity.ts | 6 ------ .../snowball/entity/decoration-prefix.entity.ts | 10 +--------- .../snowball/entity/snowball-decoration.entity.ts | 8 -------- back/src/modules/snowball/snowball.service.ts | 1 - 5 files changed, 2 insertions(+), 29 deletions(-) diff --git a/back/src/modules/message/entity/letter.entity.ts b/back/src/modules/message/entity/letter.entity.ts index 26ae4bb..b3f02fc 100644 --- a/back/src/modules/message/entity/letter.entity.ts +++ b/back/src/modules/message/entity/letter.entity.ts @@ -1,11 +1,7 @@ -import { Entity, PrimaryGeneratedColumn, OneToMany } from 'typeorm'; -import { MessageEntity } from './message.entity'; +import { Entity, PrimaryGeneratedColumn } from 'typeorm'; @Entity({ name: 'letter_prefix' }) export class LetterEntity { @PrimaryGeneratedColumn() id: number; - - @OneToMany(() => MessageEntity, message => message.letter_id) - messages: MessageEntity[]; } diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 15dcf37..0a59dcf 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -8,7 +8,6 @@ import { } from 'typeorm'; import { SnowballEntity } from 'src/modules/snowball/entity/snowball.entity'; import { UserEntity } from 'src/modules/auth/entity/user.entity'; -import { LetterEntity } from './letter.entity'; @Entity({ synchronize: true, name: 'message' }) export class MessageEntity { @@ -52,9 +51,4 @@ export class MessageEntity { @ManyToOne(() => UserEntity, user => user.messages) @JoinColumn({ name: 'user_id' }) user: UserEntity; - - //many to one relation letter_id with id in LetterEntity in letter.entity.ts - @ManyToOne(() => LetterEntity, letter => letter.messages) - @JoinColumn({ name: 'letter_id' }) - letter: LetterEntity; } diff --git a/back/src/modules/snowball/entity/decoration-prefix.entity.ts b/back/src/modules/snowball/entity/decoration-prefix.entity.ts index e761fd9..819ee1e 100644 --- a/back/src/modules/snowball/entity/decoration-prefix.entity.ts +++ b/back/src/modules/snowball/entity/decoration-prefix.entity.ts @@ -1,14 +1,6 @@ -import { Entity, PrimaryGeneratedColumn, OneToMany } from 'typeorm'; -import { SnowballDecorationEntity } from './snowball-decoration.entity'; - +import { Entity, PrimaryGeneratedColumn } from 'typeorm'; @Entity({ name: 'decoration_prefix' }) export class DecorationPrefixEntity { @PrimaryGeneratedColumn() id: number; - - @OneToMany( - () => SnowballDecorationEntity, - snowballDecoration => snowballDecoration.decoration_id - ) - decorations: SnowballDecorationEntity[]; } diff --git a/back/src/modules/snowball/entity/snowball-decoration.entity.ts b/back/src/modules/snowball/entity/snowball-decoration.entity.ts index 52c4d44..9b25028 100644 --- a/back/src/modules/snowball/entity/snowball-decoration.entity.ts +++ b/back/src/modules/snowball/entity/snowball-decoration.entity.ts @@ -6,7 +6,6 @@ import { JoinColumn } from 'typeorm'; import { SnowballEntity } from './snowball.entity'; -import { DecorationPrefixEntity } from './decoration-prefix.entity'; @Entity({ name: 'snowball_decoration' }) export class SnowballDecorationEntity { @@ -28,11 +27,4 @@ export class SnowballDecorationEntity { @ManyToOne(() => SnowballEntity, snowball => snowball.decorations) @JoinColumn({ name: 'snowball_id' }) snowball: SnowballEntity; - - @ManyToOne( - () => DecorationPrefixEntity, - decorationPrefix => decorationPrefix.decorations - ) - @JoinColumn({ name: 'decoration_id' }) - decorationPrefix: DecorationPrefixEntity; } diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 2e15f70..84588b7 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -103,7 +103,6 @@ export class SnowballService { }) .where('id = :id', { id: snowball_id }) .execute(); - console.log(updateResult); if (!updateResult.affected) { throw new NotFoundException('업데이트할 스노우볼이 존재하지 않습니다.'); } From de62fd51afea45ed26d095000b23196bacecd01e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Fri, 24 Nov 2023 07:03:26 +0900 Subject: [PATCH 098/185] =?UTF-8?q?feat:=20createInfo=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=20=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.service.ts | 29 ++++++++++++++----- back/src/modules/auth/dto/user.dto.ts | 4 +++ .../auth/strategy/google-auth.strategy.ts | 2 +- .../modules/message/entity/letter.entity.ts | 5 +++- .../entity/decoration-prefix.entity.ts | 5 +++- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index 64a9be5..e7ae3b9 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -39,17 +39,25 @@ export class AuthService { where: { user_id: user.id } }); - let userId; + let userId: number, + snowball_count: number, + message_count: number, + snowball_list: { id: number; uuid: string }[], + main_snowball_id: number | null; if (exisitingUser) { userId = exisitingUser.id; - const snowballCount = await this.SnowballRepository.findAndCount({ + const snowballs = await this.SnowballRepository.findAndCount({ where: { user_id: userId } }); - const snowballList = await this.SnowballRepository.find({ - where: { user_id: userId } + snowball_count = snowballs[1]; + snowball_list = snowballs[0].map(snowball => { + return { + id: snowball.id, + uuid: snowball.snowball_uuid + }; }); - console.log(snowballCount, snowballList); + main_snowball_id = snowballs[0][0].id; } else { const newUser: UserEntity = this.UserRepository.create({ user_id: user.id, @@ -60,14 +68,19 @@ export class AuthService { const saveduser = await this.UserRepository.insert(newUser); userId = saveduser.identifiers.pop().id; + snowball_count = 0; + message_count = 0; + snowball_list = []; + main_snowball_id = null; } const userDto: UserDto = { id: userId, name: user.name, auth_id: user.id, - snowball_count: 3, - snowball_list: [], - message_count: 123 + snowball_count: snowball_count, + main_snowball_id: main_snowball_id, + snowball_list: snowball_list, + message_count: message_count }; return userDto; } diff --git a/back/src/modules/auth/dto/user.dto.ts b/back/src/modules/auth/dto/user.dto.ts index 2c2edb0..790fed3 100644 --- a/back/src/modules/auth/dto/user.dto.ts +++ b/back/src/modules/auth/dto/user.dto.ts @@ -22,6 +22,10 @@ export class UserDto { @ApiProperty({ type: Number, description: '스노우볼 갯수' }) readonly snowball_count: number; + @IsNumber() + @ApiProperty({ type: Number, description: '메인 스노우볼 id' }) + readonly main_snowball_id: number; + @IsNotEmpty() @ApiProperty({ type: 'array', diff --git a/back/src/modules/auth/strategy/google-auth.strategy.ts b/back/src/modules/auth/strategy/google-auth.strategy.ts index 963477e..13762e1 100644 --- a/back/src/modules/auth/strategy/google-auth.strategy.ts +++ b/back/src/modules/auth/strategy/google-auth.strategy.ts @@ -9,7 +9,7 @@ export class GoogleAuthStrategy extends PassportStrategy(Strategy, 'google') { clientID: `${process.env.GOOGLE_CLIENT_ID}`, clientSecret: `${process.env.GOOGLE_SECRET}`, callbackURL: 'http://www.mysnowball.kr/api/auth/google/redirect', - //callbackURL: 'http://localhost:3000/api/auth/google/redirect', + //callbackURL: 'http://localhost:3000/api/auth/google/redirect', .env로 넣자.. scope: ['profile'] }); } diff --git a/back/src/modules/message/entity/letter.entity.ts b/back/src/modules/message/entity/letter.entity.ts index b3f02fc..89a4d95 100644 --- a/back/src/modules/message/entity/letter.entity.ts +++ b/back/src/modules/message/entity/letter.entity.ts @@ -1,7 +1,10 @@ -import { Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; @Entity({ name: 'letter_prefix' }) export class LetterEntity { @PrimaryGeneratedColumn() id: number; + + @Column() + active: boolean; } diff --git a/back/src/modules/snowball/entity/decoration-prefix.entity.ts b/back/src/modules/snowball/entity/decoration-prefix.entity.ts index 819ee1e..0b7e0d1 100644 --- a/back/src/modules/snowball/entity/decoration-prefix.entity.ts +++ b/back/src/modules/snowball/entity/decoration-prefix.entity.ts @@ -1,6 +1,9 @@ -import { Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; @Entity({ name: 'decoration_prefix' }) export class DecorationPrefixEntity { @PrimaryGeneratedColumn() id: number; + + @Column() + active: boolean; } From e63d738d664b188645c5e017232f2fcc232ec234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Fri, 24 Nov 2023 07:16:59 +0900 Subject: [PATCH 099/185] =?UTF-8?q?feat:=20index=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.guard.ts | 2 +- back/src/modules/auth/auth.service.ts | 5 +++-- back/src/modules/auth/entity/user.entity.ts | 2 ++ back/src/modules/auth/strategy/google-auth.strategy.ts | 3 +-- back/src/modules/auth/strategy/kakao-auth.strategy.ts | 3 +-- back/src/modules/auth/strategy/naver-auth.strategy.ts | 3 +-- back/src/modules/snowball/entity/snowball.entity.ts | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/back/src/modules/auth/auth.guard.ts b/back/src/modules/auth/auth.guard.ts index 037bb66..b0944d0 100644 --- a/back/src/modules/auth/auth.guard.ts +++ b/back/src/modules/auth/auth.guard.ts @@ -22,7 +22,7 @@ export class JWTGuard implements CanActivate { const payload = await this.jwtService.verify(token, { secret: process.env.JWT_SECRET }); - request['user'] = payload.userid; // 이거 oauth2.0 아이디라 pk로 바꿔야함 + request['user'] = payload.userid; } catch { throw new UnauthorizedException(); } diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index e7ae3b9..98a596d 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -22,8 +22,9 @@ export class AuthService { async createInfo(user: any): Promise { const jwt_token = this.generateJwtToken(user); const userDto: UserDto = await this.createUserDto(user); - const mainSnowballDto: SnowballDto = - await this.snowballService.getSnowball(1); + const mainSnowballDto: SnowballDto = await this.snowballService.getSnowball( + userDto.main_snowball_id + ); const resInfoDto: ResInfoDto = { jwt_token, diff --git a/back/src/modules/auth/entity/user.entity.ts b/back/src/modules/auth/entity/user.entity.ts index fcbac72..28f079c 100644 --- a/back/src/modules/auth/entity/user.entity.ts +++ b/back/src/modules/auth/entity/user.entity.ts @@ -3,12 +3,14 @@ import { PrimaryGeneratedColumn, Column, OneToMany, + Index, CreateDateColumn } from 'typeorm'; import { SnowballEntity } from '../../snowball/entity/snowball.entity'; import { MessageEntity } from 'src/modules/message/entity/message.entity'; @Entity({ name: 'user' }) +@Index(['user_id'], { unique: true }) export class UserEntity { @PrimaryGeneratedColumn() id: number; diff --git a/back/src/modules/auth/strategy/google-auth.strategy.ts b/back/src/modules/auth/strategy/google-auth.strategy.ts index 13762e1..6c8bf4f 100644 --- a/back/src/modules/auth/strategy/google-auth.strategy.ts +++ b/back/src/modules/auth/strategy/google-auth.strategy.ts @@ -8,8 +8,7 @@ export class GoogleAuthStrategy extends PassportStrategy(Strategy, 'google') { super({ clientID: `${process.env.GOOGLE_CLIENT_ID}`, clientSecret: `${process.env.GOOGLE_SECRET}`, - callbackURL: 'http://www.mysnowball.kr/api/auth/google/redirect', - //callbackURL: 'http://localhost:3000/api/auth/google/redirect', .env로 넣자.. + callbackURL: `${process.env.GOOGLE_CALLBACK_URL}`, scope: ['profile'] }); } diff --git a/back/src/modules/auth/strategy/kakao-auth.strategy.ts b/back/src/modules/auth/strategy/kakao-auth.strategy.ts index 04c5783..26b5ce5 100644 --- a/back/src/modules/auth/strategy/kakao-auth.strategy.ts +++ b/back/src/modules/auth/strategy/kakao-auth.strategy.ts @@ -8,8 +8,7 @@ export class KakaoAuthStrategy extends PassportStrategy(Strategy, 'kakao') { super({ clientID: `${process.env.KAKAO_CLIENT_ID}`, clientSecret: `${process.env.KAKAO_SECRET}`, - callbackURL: 'http://www.mysnowball.kr/api/auth/kakao/redirect', - //callbackURL: 'http://localhost:3000/api/auth/kakao/redirect', + callbackURL: `${process.env.KAKAO_CALLBACK_URL}`, passReqToCallback: false, scope: ['profile_nickname'] }); diff --git a/back/src/modules/auth/strategy/naver-auth.strategy.ts b/back/src/modules/auth/strategy/naver-auth.strategy.ts index 25fe47d..909b48a 100644 --- a/back/src/modules/auth/strategy/naver-auth.strategy.ts +++ b/back/src/modules/auth/strategy/naver-auth.strategy.ts @@ -8,8 +8,7 @@ export class NaverAuthStrategy extends PassportStrategy(Strategy, 'naver') { super({ clientID: `${process.env.NAVER_CLIENT_ID}`, clientSecret: `${process.env.NAVER_SECRET}`, - callbackURL: 'http://www.mysnowball.kr/api/auth/naver/redirect', - //callbackURL: 'http://localhost:3000/api/auth/naver/redirect', + callbackURL: `${process.env.NAVER_CALLBACK_URL}`, passReqToCallback: false, scope: ['profile'] }); diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index 03c942d..d0c7345 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -16,7 +16,7 @@ import { SnowballDecorationEntity } from './snowball-decoration.entity'; import { MessageEntity } from '../../message/entity/message.entity'; @Entity({ name: 'snowball' }) -@Index('idx_snowball', ['snowball_uuid'], { unique: true }) +@Index(['snowball_uuid'], { unique: true }) export class SnowballEntity { @PrimaryGeneratedColumn() id: number; From 5b9945840c8c641f9be06b4d68aa4320518f4a8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Fri, 24 Nov 2023 08:02:51 +0900 Subject: [PATCH 100/185] =?UTF-8?q?feat:=20resInfo=20=EB=93=9C=EB=94=94?= =?UTF-8?q?=EC=96=B4=20=EC=84=B1=EA=B3=B5=20=E3=85=9C=E3=85=9C=E3=85=9C?= =?UTF-8?q?=E3=85=9C=E3=85=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.guard.ts | 2 +- back/src/modules/auth/auth.service.ts | 68 +++++++++++-------- .../src/modules/message/message.controller.ts | 4 +- .../modules/snowball/snowball.controller.ts | 2 +- back/src/util/swagger.ts | 2 +- 5 files changed, 46 insertions(+), 32 deletions(-) diff --git a/back/src/modules/auth/auth.guard.ts b/back/src/modules/auth/auth.guard.ts index b0944d0..69d532b 100644 --- a/back/src/modules/auth/auth.guard.ts +++ b/back/src/modules/auth/auth.guard.ts @@ -22,7 +22,7 @@ export class JWTGuard implements CanActivate { const payload = await this.jwtService.verify(token, { secret: process.env.JWT_SECRET }); - request['user'] = payload.userid; + request['id'] = payload.user_pk; } catch { throw new UnauthorizedException(); } diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index 98a596d..6dc1855 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -20,11 +20,15 @@ export class AuthService { ) {} async createInfo(user: any): Promise { - const jwt_token = this.generateJwtToken(user); - const userDto: UserDto = await this.createUserDto(user); - const mainSnowballDto: SnowballDto = await this.snowballService.getSnowball( - userDto.main_snowball_id + const { user_pk, is_existed } = await this.getUserPk(user); + const jwt_token = this.generateJwtToken(user_pk); + const userDto: UserDto = await this.createUserDto( + user, + user_pk, + is_existed ); + const mainSnowballDto: SnowballDto = + await this.snowballService.getSnowball(1); const resInfoDto: ResInfoDto = { jwt_token, @@ -35,21 +39,18 @@ export class AuthService { return resInfoDto; } - async createUserDto(user: any): Promise { - const exisitingUser = await this.UserRepository.findOne({ - where: { user_id: user.id } - }); - - let userId: number, - snowball_count: number, + async createUserDto( + user: any, + user_pk: number, + is_existed: boolean + ): Promise { + let snowball_count: number, message_count: number, snowball_list: { id: number; uuid: string }[], main_snowball_id: number | null; - if (exisitingUser) { - userId = exisitingUser.id; - + if (is_existed) { const snowballs = await this.SnowballRepository.findAndCount({ - where: { user_id: userId } + where: { user_id: user_pk } }); snowball_count = snowballs[1]; snowball_list = snowballs[0].map(snowball => { @@ -60,22 +61,13 @@ export class AuthService { }); main_snowball_id = snowballs[0][0].id; } else { - const newUser: UserEntity = this.UserRepository.create({ - user_id: user.id, - username: user.name, - provider: user.provider, - created_at: new Date() - }); - - const saveduser = await this.UserRepository.insert(newUser); - userId = saveduser.identifiers.pop().id; snowball_count = 0; message_count = 0; snowball_list = []; main_snowball_id = null; } const userDto: UserDto = { - id: userId, + id: user_pk, name: user.name, auth_id: user.id, snowball_count: snowball_count, @@ -86,8 +78,30 @@ export class AuthService { return userDto; } - generateJwtToken(user: any): string { - const payload = { userid: user.id, username: user.name }; + async getUserPk( + user: any + ): Promise<{ user_pk: number; is_existed: boolean }> { + const exisitingUser = await this.UserRepository.findOne({ + where: { user_id: user.id } + }); + if (exisitingUser) { + return { user_pk: exisitingUser.id, is_existed: true }; + } else { + const newUser: UserEntity = this.UserRepository.create({ + user_id: user.id, + username: user.name, + provider: user.provider, + created_at: new Date() + }); + + const saveduser = await this.UserRepository.insert(newUser); + const pk = saveduser.identifiers.pop().id; + return { user_pk: pk, is_existed: false }; + } + } + + generateJwtToken(user_pk: any): string { + const payload = { user_pk: user_pk }; return this.jwtService.sign(payload); } } diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 0f8c70c..2700eda 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -83,7 +83,7 @@ export class MessageController { @Req() req: any, @Param('message_id') message_id: number ) { - await this.messageService.deleteMessage(req.user, message_id); + await this.messageService.deleteMessage(req.id, message_id); } @UseGuards(JWTGuard) @@ -104,7 +104,7 @@ export class MessageController { description: 'Find Fail' }) async getAllMessages(@Req() req: any): Promise { - const messages = await this.messageService.getAllMessages(req.user); + const messages = await this.messageService.getAllMessages(req.id); return messages; } diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index 58885d4..554afdd 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -49,7 +49,7 @@ export class SnowballController { @Body() createSnowballDto: ReqCreateSnowballDto ): Promise { const snowball = this.snowballService.createSnowball( - req.user, + req.id, createSnowballDto ); return snowball; diff --git a/back/src/util/swagger.ts b/back/src/util/swagger.ts index c0a351f..37dc4f1 100644 --- a/back/src/util/swagger.ts +++ b/back/src/util/swagger.ts @@ -21,7 +21,7 @@ export function setupSwagger(app: INestApplication): void { type: 'oauth2', flows: { authorizationCode: { - authorizationUrl: 'http://www.mysnowball.kr/api/auth/google', + authorizationUrl: `${process.env.AUTHORIZATION_URL}`, scopes: { profile: 'profile' } From 10aa290a3faa46581c418f545c635e1ed9602065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Fri, 24 Nov 2023 08:25:06 +0900 Subject: [PATCH 101/185] =?UTF-8?q?feat:=20message=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EC=8B=9C=20user=5Fid=20param=EC=9C=BC=EB=A1=9C=20=EB=B0=9B?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.controller.ts | 2 ++ back/src/modules/message/message.service.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 2700eda..0cec23a 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -51,11 +51,13 @@ export class MessageController { description: 'Insert Fail' }) async createMessage( + @Param('user_id') user_id: number, @Param('snowball_id') snowball_id: number, @Body() createMessageDto: ReqCreateMessageDto ): Promise { const resCreateMessage = await this.messageService.createMessage( createMessageDto, + user_id, snowball_id ); return resCreateMessage; diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index f4acaf5..d4ba23a 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -24,10 +24,12 @@ export class MessageService { ) {} async createMessage( createMessageDto: ReqCreateMessageDto, + user_id: number, snowball_id: number ): Promise { const messageEntity = this.messageRepository.create({ snowball_id: snowball_id, + user_id: user_id, sender: createMessageDto.sender, content: createMessageDto.content, decoration_id: createMessageDto.decoration_id, From b3ef26afbde36e1d8dd85cb8fafbcd926ede922b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Fri, 24 Nov 2023 08:37:42 +0900 Subject: [PATCH 102/185] =?UTF-8?q?fix:=20message=20create=20=EB=94=94?= =?UTF-8?q?=EB=B2=84=EA=B9=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.controller.ts | 2 -- back/src/modules/message/message.service.ts | 16 +++++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 0cec23a..2700eda 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -51,13 +51,11 @@ export class MessageController { description: 'Insert Fail' }) async createMessage( - @Param('user_id') user_id: number, @Param('snowball_id') snowball_id: number, @Body() createMessageDto: ReqCreateMessageDto ): Promise { const resCreateMessage = await this.messageService.createMessage( createMessageDto, - user_id, snowball_id ); return resCreateMessage; diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index d4ba23a..c0f9b0d 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -13,6 +13,7 @@ import { MessageEntity } from './entity/message.entity'; import { UserEntity } from '../auth/entity/user.entity'; import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; import { MessageDto } from './dto/message.dto'; +import { SnowballEntity } from '../snowball/entity/snowball.entity'; @Injectable() export class MessageService { @@ -20,16 +21,18 @@ export class MessageService { @InjectRepository(UserEntity) private readonly userRepository: Repository, @InjectRepository(MessageEntity) - private readonly messageRepository: Repository + private readonly messageRepository: Repository, + @InjectRepository(SnowballEntity) + private readonly snowballRepository: Repository ) {} async createMessage( createMessageDto: ReqCreateMessageDto, - user_id: number, snowball_id: number ): Promise { + const user_id = await this.getUserId(snowball_id); const messageEntity = this.messageRepository.create({ - snowball_id: snowball_id, user_id: user_id, + snowball_id: snowball_id, sender: createMessageDto.sender, content: createMessageDto.content, decoration_id: createMessageDto.decoration_id, @@ -138,4 +141,11 @@ export class MessageService { throw new InternalServerErrorException('서버측 오류'); } } + + async getUserId(snowball_id: number): Promise { + const snowball = await this.snowballRepository.findOne({ + where: { id: snowball_id } + }); + return snowball.user_id; + } } From 04e00d7ccdc42c2b3d1e481b0ac3cc2fdb8c7fde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Fri, 24 Nov 2023 10:56:20 +0900 Subject: [PATCH 103/185] =?UTF-8?q?feat:=20snowball=20uuid=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.service.ts | 7 ++----- back/src/modules/auth/dto/user.dto.ts | 13 +++---------- back/src/modules/message/entity/letter.entity.ts | 2 +- back/src/modules/message/message.service.ts | 11 ++++++----- back/src/modules/snowball/dto/snowball.dto.ts | 6 ------ .../snowball/entity/decoration-prefix.entity.ts | 2 +- .../modules/snowball/entity/snowball.entity.ts | 16 +--------------- back/src/modules/snowball/snowball.service.ts | 2 -- 8 files changed, 14 insertions(+), 45 deletions(-) diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index 6dc1855..1ef524d 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -46,7 +46,7 @@ export class AuthService { ): Promise { let snowball_count: number, message_count: number, - snowball_list: { id: number; uuid: string }[], + snowball_list: number[], main_snowball_id: number | null; if (is_existed) { const snowballs = await this.SnowballRepository.findAndCount({ @@ -54,10 +54,7 @@ export class AuthService { }); snowball_count = snowballs[1]; snowball_list = snowballs[0].map(snowball => { - return { - id: snowball.id, - uuid: snowball.snowball_uuid - }; + return snowball.id; }); main_snowball_id = snowballs[0][0].id; } else { diff --git a/back/src/modules/auth/dto/user.dto.ts b/back/src/modules/auth/dto/user.dto.ts index 790fed3..60f8d03 100644 --- a/back/src/modules/auth/dto/user.dto.ts +++ b/back/src/modules/auth/dto/user.dto.ts @@ -28,17 +28,10 @@ export class UserDto { @IsNotEmpty() @ApiProperty({ - type: 'array', - items: { - type: 'object', - properties: { - id: { type: 'number' }, - uuid: { type: 'string' } - } - }, - description: '스노우볼 key-value 리스트' + type: [Number], + description: '스노우볼 id 리스트' }) - readonly snowball_list: { id: number; uuid: string }[]; + readonly snowball_list: number[]; @IsNumber() @IsNotEmpty() diff --git a/back/src/modules/message/entity/letter.entity.ts b/back/src/modules/message/entity/letter.entity.ts index 89a4d95..04dfde1 100644 --- a/back/src/modules/message/entity/letter.entity.ts +++ b/back/src/modules/message/entity/letter.entity.ts @@ -5,6 +5,6 @@ export class LetterEntity { @PrimaryGeneratedColumn() id: number; - @Column() + @Column({ type: 'boolean', default: true }) active: boolean; } diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index c0f9b0d..56cb605 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -37,8 +37,9 @@ export class MessageService { content: createMessageDto.content, decoration_id: createMessageDto.decoration_id, decoration_color: createMessageDto.decoration_color, - letter_id: createMessageDto.letter_id - // opened와 created는 자동으로 설정 + letter_id: createMessageDto.letter_id, + opened: null + // is_deleted랑 created는 자동으로 설정 }); const savedMessage = await this.messageRepository.save(messageEntity); @@ -88,9 +89,9 @@ export class MessageService { if (!user) { throw new NotFoundException(`User with id ${user_id} not found`); } - const messages: MessageEntity[] = user.snowballs.flatMap( - snowball => snowball.messages - ); + const messages: MessageEntity[] = user.snowballs + .flatMap(snowball => snowball.messages) + .filter(message => !message.is_deleted); const messagesDto: MessageDto[] = messages.map(message => { const { id, diff --git a/back/src/modules/snowball/dto/snowball.dto.ts b/back/src/modules/snowball/dto/snowball.dto.ts index 71b0b0c..daee549 100644 --- a/back/src/modules/snowball/dto/snowball.dto.ts +++ b/back/src/modules/snowball/dto/snowball.dto.ts @@ -1,6 +1,5 @@ import { IsString, - IsUUID, IsBoolean, IsNumber, IsNotEmpty, @@ -22,11 +21,6 @@ export class SnowballDto { @ApiProperty({ type: Number, description: '스노우볼 id' }) readonly id: number; - @IsUUID('4') - @IsNotEmpty() - @ApiProperty({ format: 'uuid', description: '스노우볼 UUID' }) - readonly uuid: string; - @IsBoolean() @IsNotEmpty() @ApiProperty({ diff --git a/back/src/modules/snowball/entity/decoration-prefix.entity.ts b/back/src/modules/snowball/entity/decoration-prefix.entity.ts index 0b7e0d1..82cf54b 100644 --- a/back/src/modules/snowball/entity/decoration-prefix.entity.ts +++ b/back/src/modules/snowball/entity/decoration-prefix.entity.ts @@ -4,6 +4,6 @@ export class DecorationPrefixEntity { @PrimaryGeneratedColumn() id: number; - @Column() + @Column({ type: 'boolean', default: true }) active: boolean; } diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index d0c7345..a85163b 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -1,22 +1,17 @@ -import { IsUUID } from '@nestjs/class-validator'; -import { v4 as uuidv4 } from 'uuid'; import { Entity, Column, - Index, PrimaryGeneratedColumn, CreateDateColumn, ManyToOne, OneToMany, - JoinColumn, - BeforeInsert + JoinColumn } from 'typeorm'; import { UserEntity } from '../../auth/entity/user.entity'; import { SnowballDecorationEntity } from './snowball-decoration.entity'; import { MessageEntity } from '../../message/entity/message.entity'; @Entity({ name: 'snowball' }) -@Index(['snowball_uuid'], { unique: true }) export class SnowballEntity { @PrimaryGeneratedColumn() id: number; @@ -24,10 +19,6 @@ export class SnowballEntity { @Column() user_id: number; - @IsUUID('4') - @Column({ length: 36 }) - snowball_uuid: string; - @Column({ length: 16 }) title: string; @@ -46,9 +37,4 @@ export class SnowballEntity { @OneToMany(() => SnowballDecorationEntity, decoration => decoration.snowball) decorations: SnowballDecorationEntity[]; - - @BeforeInsert() - generateSnowballUUID() { - this.snowball_uuid = uuidv4(); - } } diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 84588b7..9b0d74c 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -38,7 +38,6 @@ export class SnowballService { } const combinedSnowballDto: SnowballDto = { id: savedSnowball.id, - uuid: savedSnowball.snowball_uuid, title: savedSnowball.title, is_message_private: savedSnowball.message_private === null ? false : true, deco_list: decoList, @@ -131,7 +130,6 @@ export class SnowballService { const resSnowball: SnowballDto = { id: snowball.id, - uuid: snowball.snowball_uuid, title: snowball.title, is_message_private: snowball.message_private ? true : false, deco_list: snowball.decorations, From 395fdcb106d97ab4e37d420ace96161fea307cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Fri, 24 Nov 2023 17:54:06 +0900 Subject: [PATCH 104/185] =?UTF-8?q?feat:=20visitor=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.controller.ts | 26 ++++- back/src/modules/auth/auth.module.ts | 8 +- back/src/modules/auth/auth.service.ts | 106 +++++++++++++----- .../auth/dto/response/res-visit-info.do.ts | 20 ++++ back/src/modules/auth/dto/user.dto.ts | 2 +- 5 files changed, 127 insertions(+), 35 deletions(-) create mode 100644 back/src/modules/auth/dto/response/res-visit-info.do.ts diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index ce20fa7..3b57852 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -1,8 +1,9 @@ -import { Controller, Get, Req, UseGuards } from '@nestjs/common'; +import { Controller, Get, Req, Param, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; import { ResInfoDto } from './dto/response/res-info.dto'; import { AuthService } from './auth.service'; +import { ResVisitInfoDto } from './dto/response/res-visit-info.do'; @ApiTags('Oauth API') @Controller('auth') @@ -38,7 +39,7 @@ export class AuthController { }) async googleLoginCallback(@Req() req): Promise { const userInfo = req.user; - const result = this.authService.createInfo(userInfo); + const result = this.authService.createUserInfo(userInfo); return result; } @@ -72,7 +73,7 @@ export class AuthController { }) async naverLoginCallBack(@Req() req): Promise { const userInfo = req.user; - const result = this.authService.createInfo(userInfo); + const result = this.authService.createUserInfo(userInfo); return result; } @@ -106,7 +107,24 @@ export class AuthController { }) async kakaoLoginCallBack(@Req() req): Promise { const userInfo = req.user; - const result = this.authService.createInfo(userInfo); + const result = this.authService.createUserInfo(userInfo); + return result; + } + + @Get('visit/:user_id') + @ApiOperation({ + summary: '방문자 유저 조회 API', + description: '방문자가 접속한 유저의 정보를 반환합니다' + }) + @ApiResponse({ + status: 500, + description: 'Internal Server Error', + type: ResVisitInfoDto + }) + async createVisitInfo( + @Param('user_id') user_id: string + ): Promise { + const result = this.authService.createVisitInfo(user_id); return result; } } diff --git a/back/src/modules/auth/auth.module.ts b/back/src/modules/auth/auth.module.ts index 5b8b37e..e903e43 100644 --- a/back/src/modules/auth/auth.module.ts +++ b/back/src/modules/auth/auth.module.ts @@ -9,15 +9,17 @@ import { SnowballService } from '../snowball/snowball.service'; import { TypeOrmModule } from '@nestjs/typeorm'; import { SnowballEntity } from '../snowball/entity/snowball.entity'; import { UserEntity } from './entity/user.entity'; -import { SnowballDecorationEntity } from '../snowball/entity/snowball-decoration.entity'; import { JWTGuard } from './auth.guard'; +import { MessageEntity } from '../message/entity/message.entity'; +import { SnowballDecorationEntity } from '../snowball/entity/snowball-decoration.entity'; @Module({ imports: [ TypeOrmModule.forFeature([ - SnowballEntity, UserEntity, - SnowballDecorationEntity + SnowballEntity, + SnowballDecorationEntity, + MessageEntity ]), PassportModule ], diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index 1ef524d..a156085 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, NotFoundException } from '@nestjs/common'; import { ResInfoDto } from './dto/response/res-info.dto'; import { UserDto } from './dto/user.dto'; import { SnowballDto } from '../snowball/dto/snowball.dto'; @@ -8,6 +8,14 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { UserEntity } from './entity/user.entity'; import { SnowballEntity } from '../snowball/entity/snowball.entity'; +import { ResVisitInfoDto } from './dto/response/res-visit-info.do'; +import { MessageEntity } from '../message/entity/message.entity'; +interface SnowballInfo { + snowball_count: number; + message_count: number; + snowball_list: number[]; + main_snowball_id: number | null; +} @Injectable() export class AuthService { constructor( @@ -15,20 +23,22 @@ export class AuthService { private readonly UserRepository: Repository, @InjectRepository(SnowballEntity) private readonly SnowballRepository: Repository, + @InjectRepository(MessageEntity) + private readonly MessageRepository: Repository, private readonly jwtService: JwtService, private readonly snowballService: SnowballService ) {} - async createInfo(user: any): Promise { + async createUserInfo(user: any): Promise { const { user_pk, is_existed } = await this.getUserPk(user); const jwt_token = this.generateJwtToken(user_pk); const userDto: UserDto = await this.createUserDto( - user, user_pk, + user.name, + user.id, is_existed ); - const mainSnowballDto: SnowballDto = - await this.snowballService.getSnowball(1); + const mainSnowballDto = await this.getMainSnowballDto(userDto); const resInfoDto: ResInfoDto = { jwt_token, @@ -39,34 +49,39 @@ export class AuthService { return resInfoDto; } + async createVisitInfo(user_id: string): Promise { + const user = await this.UserRepository.findOne({ + where: { user_id: user_id } + }); + if (!user) throw new NotFoundException('해당 유저를 찾을 수 없습니다.'); + const userDto: UserDto = await this.createUserDto( + user.id, + user.username, + user.user_id, + true + ); + const mainSnowballDto = await this.getMainSnowballDto(userDto); + + const resVisitInfo: ResVisitInfoDto = { + user: userDto, + main_snowball: mainSnowballDto + }; + return resVisitInfo; + } + async createUserDto( - user: any, user_pk: number, + username: string, + user_id: string, is_existed: boolean ): Promise { - let snowball_count: number, - message_count: number, - snowball_list: number[], - main_snowball_id: number | null; - if (is_existed) { - const snowballs = await this.SnowballRepository.findAndCount({ - where: { user_id: user_pk } - }); - snowball_count = snowballs[1]; - snowball_list = snowballs[0].map(snowball => { - return snowball.id; - }); - main_snowball_id = snowballs[0][0].id; - } else { - snowball_count = 0; - message_count = 0; - snowball_list = []; - main_snowball_id = null; - } + const { snowball_count, message_count, snowball_list, main_snowball_id } = + await this.getSnowballInfo(user_pk, is_existed); + const userDto: UserDto = { id: user_pk, - name: user.name, - auth_id: user.id, + name: username, + auth_id: user_id, snowball_count: snowball_count, main_snowball_id: main_snowball_id, snowball_list: snowball_list, @@ -97,6 +112,43 @@ export class AuthService { } } + async getMainSnowballDto(userDto: UserDto): Promise { + if (!userDto.main_snowball_id) { + return null; + } else { + return await this.snowballService.getSnowball(userDto.main_snowball_id); + } + } + + async getSnowballInfo( + user_pk: number, + is_existed: boolean + ): Promise { + if (is_existed) { + const snowballs = await this.SnowballRepository.findAndCount({ + where: { user_id: user_pk } + }); + const snowball_list = snowballs[0].map(snowball => snowball.id); + return { + snowball_count: snowballs[1], + message_count: await this.getMessageCount(user_pk), + snowball_list, + main_snowball_id: snowballs[0][0].id + }; + } else { + return { + snowball_count: 0, + message_count: 0, + snowball_list: [], + main_snowball_id: null + }; + } + } + + async getMessageCount(user_pk: number): Promise { + return this.MessageRepository.count({ where: { user: { id: user_pk } } }); + } + generateJwtToken(user_pk: any): string { const payload = { user_pk: user_pk }; return this.jwtService.sign(payload); diff --git a/back/src/modules/auth/dto/response/res-visit-info.do.ts b/back/src/modules/auth/dto/response/res-visit-info.do.ts new file mode 100644 index 0000000..4126459 --- /dev/null +++ b/back/src/modules/auth/dto/response/res-visit-info.do.ts @@ -0,0 +1,20 @@ +import { IsNotEmpty } from '@nestjs/class-validator'; +import { ApiProperty } from '@nestjs/swagger'; +import { UserDto } from '../user.dto'; +import { SnowballDto } from '../../../snowball/dto/snowball.dto'; + +export class ResVisitInfoDto { + @IsNotEmpty() + @ApiProperty({ + type: UserDto, + description: '사용자 정보 ' + }) + readonly user: UserDto; + + @IsNotEmpty() + @ApiProperty({ + type: SnowballDto, + description: '메인 스노우볼 정보' + }) + readonly main_snowball: SnowballDto | null; +} diff --git a/back/src/modules/auth/dto/user.dto.ts b/back/src/modules/auth/dto/user.dto.ts index 60f8d03..bd74169 100644 --- a/back/src/modules/auth/dto/user.dto.ts +++ b/back/src/modules/auth/dto/user.dto.ts @@ -24,7 +24,7 @@ export class UserDto { @IsNumber() @ApiProperty({ type: Number, description: '메인 스노우볼 id' }) - readonly main_snowball_id: number; + readonly main_snowball_id: number | null; @IsNotEmpty() @ApiProperty({ From 0b8478e13b25c0ef2f528a610310c3d3d09dbf66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Fri, 24 Nov 2023 17:59:57 +0900 Subject: [PATCH 105/185] =?UTF-8?q?fix:=20err=EB=A5=BC=20try=20catch?= =?UTF-8?q?=EB=A1=9C=20=EA=B0=90=EC=8B=B8=EC=84=9C=20=EB=AA=A8=EB=93=A0=20?= =?UTF-8?q?err=EA=B0=80=20500=EC=B2=98=EB=A6=AC=EB=90=98=EB=8D=98=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.service.ts | 41 ++++++++++----------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 56cb605..991bb99 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -118,29 +118,26 @@ export class MessageService { } async openMessage(message_id: number): Promise { - try { - const message = await this.messageRepository.findOne({ - where: { id: message_id } - }); - if (!message) { - throw new NotFoundException( - `${message_id} 메시지를 찾을 수 없었습니다.` - ); - } - if (message.opened !== null) { - throw new ConflictException( - `${message_id} 메시지는 이미 열려있습니다.` - ); - } - const date = new Date(); - await this.messageRepository.update(message_id, { opened: date }); - return { - ...message, - opened: date - }; - } catch (err) { - throw new InternalServerErrorException('서버측 오류'); + const message = await this.messageRepository.findOne({ + where: { id: message_id } + }); + console.log(message); + if (!message) { + throw new NotFoundException( + `${message_id}번 메시지를 찾을 수 없었습니다.` + ); } + if (message.opened !== null) { + throw new ConflictException( + `${message_id}번 메시지는 이미 열려있습니다.` + ); + } + const date = new Date(); + await this.messageRepository.update(message_id, { opened: date }); + return { + ...message, + opened: date + }; } async getUserId(snowball_id: number): Promise { From 9e744b1ccc4a6ff1457c0a5a29289488b12df8c4 Mon Sep 17 00:00:00 2001 From: peageon Date: Mon, 27 Nov 2023 17:33:19 +0900 Subject: [PATCH 106/185] =?UTF-8?q?fix:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=8B=A4=ED=8C=A8=20snowballs[0][0]=20undefined=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.service.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index a156085..5da2f3b 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -124,10 +124,11 @@ export class AuthService { user_pk: number, is_existed: boolean ): Promise { - if (is_existed) { - const snowballs = await this.SnowballRepository.findAndCount({ - where: { user_id: user_pk } - }); + const snowballs = await this.SnowballRepository.findAndCount({ + where: { user_id: user_pk } + }); + console.log(snowballs); + if (is_existed && snowballs[0].length > 0) { const snowball_list = snowballs[0].map(snowball => snowball.id); return { snowball_count: snowballs[1], From af193b3e839bb2adb61b6ef2668f06bf26d46ce8 Mon Sep 17 00:00:00 2001 From: peageon Date: Mon, 27 Nov 2023 17:38:37 +0900 Subject: [PATCH 107/185] =?UTF-8?q?refactor:=20=EC=BD=98=EC=86=94=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=ED=95=98=EB=8A=94=20=EB=9D=BC=EC=9D=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index 5da2f3b..13ce9c4 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -127,7 +127,7 @@ export class AuthService { const snowballs = await this.SnowballRepository.findAndCount({ where: { user_id: user_pk } }); - console.log(snowballs); + if (is_existed && snowballs[0].length > 0) { const snowball_list = snowballs[0].map(snowball => snowball.id); return { From 8c1d109e2091de712f4c87aa439a7657ac2d108b Mon Sep 17 00:00:00 2001 From: peageon Date: Mon, 27 Nov 2023 17:54:53 +0900 Subject: [PATCH 108/185] =?UTF-8?q?feat:=20enable=20Cors=20(=EB=AF=BC?= =?UTF-8?q?=EC=95=84=EC=9A=94=EC=B2=AD)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/main.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/back/src/main.ts b/back/src/main.ts index 553fc70..f12225b 100644 --- a/back/src/main.ts +++ b/back/src/main.ts @@ -4,7 +4,8 @@ import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); - app.setGlobalPrefix('api') + app.setGlobalPrefix('api'); + app.enableCors(); setupSwagger(app); await app.listen(3000); } From 9ce77fc9de42aba43f7da0af99b4f5c54112d227 Mon Sep 17 00:00:00 2001 From: peageon Date: Mon, 27 Nov 2023 17:58:05 +0900 Subject: [PATCH 109/185] =?UTF-8?q?fix:=20cors=20=EB=A7=89=EC=95=84?= =?UTF-8?q?=EB=86=93=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/main.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/back/src/main.ts b/back/src/main.ts index f12225b..5eebd09 100644 --- a/back/src/main.ts +++ b/back/src/main.ts @@ -5,7 +5,6 @@ import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.setGlobalPrefix('api'); - app.enableCors(); setupSwagger(app); await app.listen(3000); } From 71bb354902ea99a25235e47713926fd08e54e257 Mon Sep 17 00:00:00 2001 From: peageon Date: Mon, 27 Nov 2023 18:33:37 +0900 Subject: [PATCH 110/185] =?UTF-8?q?fix:=20google=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=ED=94=84=EB=A1=A0=ED=8A=B8=20=ED=99=88=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=A6=AC=EB=8B=A4=EC=9D=B4=EB=A0=89=ED=8A=B8=ED=95=B4=EC=A3=BC?= =?UTF-8?q?=EB=8A=94=EA=B1=B8=EB=A1=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.controller.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index 3b57852..877b3e7 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Get, Req, Param, UseGuards } from '@nestjs/common'; +import { Controller, Get, Req, Param, UseGuards, Res } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; import { ResInfoDto } from './dto/response/res-info.dto'; @@ -37,10 +37,10 @@ export class AuthController { status: 500, description: 'Internal Server Error' }) - async googleLoginCallback(@Req() req): Promise { + async googleLoginCallBack(@Req() req, @Res() res): Promise { const userInfo = req.user; const result = this.authService.createUserInfo(userInfo); - return result; + res.status(200).redirect('http://www.mysnowball.kr').send(result); } @Get('naver') From e56391f9875c8cdd1760a8278e6c611909ab4eca Mon Sep 17 00:00:00 2001 From: peageon Date: Mon, 27 Nov 2023 18:40:58 +0900 Subject: [PATCH 111/185] =?UTF-8?q?fix:=20=EB=A6=AC=EB=94=94=EB=A0=89?= =?UTF-8?q?=ED=8A=B8=20=EB=8B=A4=EC=8B=9C=20=EC=95=88=ED=95=98=EB=8A=94?= =?UTF-8?q?=EA=B1=B8=EB=A1=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.controller.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index 877b3e7..3b57852 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Get, Req, Param, UseGuards, Res } from '@nestjs/common'; +import { Controller, Get, Req, Param, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; import { ResInfoDto } from './dto/response/res-info.dto'; @@ -37,10 +37,10 @@ export class AuthController { status: 500, description: 'Internal Server Error' }) - async googleLoginCallBack(@Req() req, @Res() res): Promise { + async googleLoginCallback(@Req() req): Promise { const userInfo = req.user; const result = this.authService.createUserInfo(userInfo); - res.status(200).redirect('http://www.mysnowball.kr').send(result); + return result; } @Get('naver') From afa98f9fef697c5f0e83ac5ccb2695af4148a9a8 Mon Sep 17 00:00:00 2001 From: peageon Date: Tue, 28 Nov 2023 03:11:56 +0900 Subject: [PATCH 112/185] =?UTF-8?q?feat:=20/api/snowball/:snowball=5Fid/de?= =?UTF-8?q?coration=20api=20=EB=82=98=EB=88=84=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PUT main_decoration 변경 API - /api/snowball/{snowball_id}/decoration PUT decoration_id, decoration_color 바꾸는 api - /api/message/{message_id}/decoration PUT location 바꾸는 API - /api/message/{message_id}/location --- back/src/modules/auth/auth.module.ts | 8 +- back/src/modules/message/dto/message.dto.ts | 4 + .../req-update-message-decoration.dto.ts | 14 +++ .../req-update-message-location.dto.ts | 9 ++ .../modules/message/entity/message.entity.ts | 3 + .../src/modules/message/message.controller.ts | 65 +++++++++++++ back/src/modules/message/message.service.ts | 54 ++++++++++- .../snowball/dto/decoration-snowball.dto.ts | 19 ---- .../dto/request/req-create-snowball.dto.ts | 14 +-- .../dto/request/req-update-decoration.dto.ts | 15 --- .../dto/response/res-update-decoration.dto.ts | 20 ---- back/src/modules/snowball/dto/snowball.dto.ts | 18 ++-- .../dto/update-main-decoration.dto.ts | 19 ++++ .../entity/snowball-decoration.entity.ts | 30 ------ .../snowball/entity/snowball.entity.ts | 10 +- .../modules/snowball/snowball.controller.ts | 48 +++++----- back/src/modules/snowball/snowball.module.ts | 7 +- back/src/modules/snowball/snowball.service.ts | 91 +++++++------------ 18 files changed, 241 insertions(+), 207 deletions(-) create mode 100644 back/src/modules/message/dto/request/req-update-message-decoration.dto.ts create mode 100644 back/src/modules/message/dto/request/req-update-message-location.dto.ts delete mode 100644 back/src/modules/snowball/dto/decoration-snowball.dto.ts delete mode 100644 back/src/modules/snowball/dto/request/req-update-decoration.dto.ts delete mode 100644 back/src/modules/snowball/dto/response/res-update-decoration.dto.ts create mode 100644 back/src/modules/snowball/dto/update-main-decoration.dto.ts delete mode 100644 back/src/modules/snowball/entity/snowball-decoration.entity.ts diff --git a/back/src/modules/auth/auth.module.ts b/back/src/modules/auth/auth.module.ts index e903e43..7ef8005 100644 --- a/back/src/modules/auth/auth.module.ts +++ b/back/src/modules/auth/auth.module.ts @@ -11,16 +11,10 @@ import { SnowballEntity } from '../snowball/entity/snowball.entity'; import { UserEntity } from './entity/user.entity'; import { JWTGuard } from './auth.guard'; import { MessageEntity } from '../message/entity/message.entity'; -import { SnowballDecorationEntity } from '../snowball/entity/snowball-decoration.entity'; @Module({ imports: [ - TypeOrmModule.forFeature([ - UserEntity, - SnowballEntity, - SnowballDecorationEntity, - MessageEntity - ]), + TypeOrmModule.forFeature([UserEntity, SnowballEntity, MessageEntity]), PassportModule ], providers: [ diff --git a/back/src/modules/message/dto/message.dto.ts b/back/src/modules/message/dto/message.dto.ts index 46228a8..cd41628 100644 --- a/back/src/modules/message/dto/message.dto.ts +++ b/back/src/modules/message/dto/message.dto.ts @@ -33,4 +33,8 @@ export class MessageDto { @IsDate() @ApiProperty({ type: Date, description: '생성 날짜' }) readonly created: Date; + + @IsNumber() + @ApiProperty({ type: Number, description: '위치값' }) + readonly location: number; } diff --git a/back/src/modules/message/dto/request/req-update-message-decoration.dto.ts b/back/src/modules/message/dto/request/req-update-message-decoration.dto.ts new file mode 100644 index 0000000..dc8d98d --- /dev/null +++ b/back/src/modules/message/dto/request/req-update-message-decoration.dto.ts @@ -0,0 +1,14 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsNumber, IsNotEmpty, IsHexColor } from 'class-validator'; + +export class ReqUpdateMessageDecorationDto { + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '장식 id' }) + readonly decoration_id: number; + + @IsHexColor() + @IsNotEmpty() + @ApiProperty({ type: String, description: '장식 색상', example: '#FFFFFF' }) + readonly decoration_color: string; +} diff --git a/back/src/modules/message/dto/request/req-update-message-location.dto.ts b/back/src/modules/message/dto/request/req-update-message-location.dto.ts new file mode 100644 index 0000000..4a6d01e --- /dev/null +++ b/back/src/modules/message/dto/request/req-update-message-location.dto.ts @@ -0,0 +1,9 @@ +import { IsNotEmpty, IsNumber } from '@nestjs/class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class ReqUpdateMessageLocationDto { + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '메시지 위치' }) + readonly location: number; +} diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 0a59dcf..0856f59 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -38,6 +38,9 @@ export class MessageEntity { @Column({ type: 'boolean', default: false }) is_deleted: boolean; + @Column({ nullable: false }) + location: number; + @CreateDateColumn({ nullable: true, default: null }) opened: Date | null; diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 2700eda..9c98e28 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -28,6 +28,8 @@ import { import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; import { MessageDto } from './dto/message.dto'; import { JWTGuard } from '../auth/auth.guard'; +import { ReqUpdateMessageDecorationDto } from './dto/request/req-update-message-decoration.dto'; +import { ReqUpdateMessageLocationDto } from './dto/request/req-update-message-location.dto'; @ApiTags('Message API') @Controller('message') @@ -137,4 +139,67 @@ export class MessageController { ): Promise { return await this.messageService.openMessage(message_id); } + + @UseGuards(JWTGuard) + @ApiBearerAuth('jwt-token') + @Put('/:message_id/decoration') + @ApiOperation({ + summary: '메세지 장식 변경', + description: '메시지의 장식을 변경합니다.' + }) + @ApiResponse({ + status: 200, + type: MessageDto + }) + @ApiBadRequestResponse({ + description: '잘못된 요청입니다.' + }) + @ApiNotFoundResponse({ + description: '해당 메시지가 존재하지 않습니다.' + }) + @ApiInternalServerErrorResponse({ + description: '서버측 오류' + }) + async updateMessageDecoration( + @Param('message_id') message_id: number, + @Body() updateMessageDecorationDto: ReqUpdateMessageDecorationDto + ): Promise { + return await this.messageService.updateMessageDecoration( + message_id, + updateMessageDecorationDto + ); + } + + @UseGuards(JWTGuard) + @ApiBearerAuth('jwt-token') + @Put('/:message_id/location') + @ApiOperation({ + summary: '메세지 위치 변경', + description: '메시지의 위치를 변경합니다.' + }) + @ApiResponse({ + status: 200, + type: MessageDto + }) + @ApiBadRequestResponse({ + description: '잘못된 요청입니다.' + }) + @ApiNotFoundResponse({ + description: '해당 메시지가 존재하지 않습니다.' + }) + @ApiInternalServerErrorResponse({ + description: '서버측 오류' + }) + @ApiConflictResponse({ + description: '목표 위치가 비어있지 않습니다.' + }) + async updateMessageLocation( + @Param('message_id') message_id: number, + @Body() updateMessageLocationDto: ReqUpdateMessageLocationDto + ): Promise { + return await this.messageService.updateMessageLocation( + message_id, + updateMessageLocationDto + ); + } } diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 991bb99..121ebbb 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -14,6 +14,8 @@ import { UserEntity } from '../auth/entity/user.entity'; import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; import { MessageDto } from './dto/message.dto'; import { SnowballEntity } from '../snowball/entity/snowball.entity'; +import { ReqUpdateMessageDecorationDto } from './dto/request/req-update-message-decoration.dto'; +import { ReqUpdateMessageLocationDto } from './dto/request/req-update-message-location.dto'; @Injectable() export class MessageService { @@ -101,7 +103,8 @@ export class MessageService { content, sender, opened, - created + created, + location } = message; return { id, @@ -111,7 +114,8 @@ export class MessageService { content, sender, opened, - created + created, + location }; }); return messagesDto; @@ -146,4 +150,50 @@ export class MessageService { }); return snowball.user_id; } + + async updateMessageDecoration( + message_id: number, + updateMessageDecorationDto: ReqUpdateMessageDecorationDto + ): Promise { + const { decoration_id, decoration_color } = updateMessageDecorationDto; + const updateResult = await this.messageRepository + .createQueryBuilder() + .update(MessageEntity) + .set({ + decoration_id, + decoration_color + }) + .where('id = :id', { id: message_id }) + .returning('*') + .execute(); + if (!updateResult.affected) { + throw new NotFoundException('업데이트할 메시지가 존재하지 않습니다.'); + } else if (updateResult.affected > 1) { + throw new InternalServerErrorException('서버측 오류'); + } + return updateResult.raw[0] as MessageDto; + } + + async updateMessageLocation( + message_id: number, + updateMessageLocationDto: ReqUpdateMessageLocationDto + ): Promise { + //TODO: location이 available 한지 확인 해야함 + const { location } = updateMessageLocationDto; + const updateResult = await this.messageRepository + .createQueryBuilder() + .update(MessageEntity) + .set({ + location + }) + .where('id = :id', { id: message_id }) + .returning('*') + .execute(); + if (!updateResult.affected) { + throw new NotFoundException('업데이트할 메시지가 존재하지 않습니다.'); + } else if (updateResult.affected > 1) { + throw new InternalServerErrorException('서버측 오류'); + } + return updateResult.raw[0] as MessageDto; + } } diff --git a/back/src/modules/snowball/dto/decoration-snowball.dto.ts b/back/src/modules/snowball/dto/decoration-snowball.dto.ts deleted file mode 100644 index f43b34c..0000000 --- a/back/src/modules/snowball/dto/decoration-snowball.dto.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { IsNumber, IsNotEmpty, IsString } from '@nestjs/class-validator'; -import { ApiProperty } from '@nestjs/swagger'; - -export class DecorationSnowballDto { - @IsNumber() - @IsNotEmpty() - @ApiProperty({ type: Number, description: '장식 종류' }) - readonly decoration_id: number; - - @IsString() - @IsNotEmpty() - @ApiProperty({ type: String, description: '장식 색상', example: '#FFFFFF' }) - readonly decoration_color: string; - - @IsNumber() - @IsNotEmpty() - @ApiProperty({ type: Number, description: '위치값' }) - readonly location: number; -} diff --git a/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts b/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts index 8d2caea..45cc886 100644 --- a/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts @@ -2,23 +2,11 @@ import { IsString, IsNumber, IsNotEmpty, - IsBoolean, - ValidateNested + IsBoolean } from '@nestjs/class-validator'; -import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; -import { DecorationSnowballDto } from '../decoration-snowball.dto'; export class ReqCreateSnowballDto { - @IsNotEmpty() - @ValidateNested({ each: true }) - @Type(() => DecorationSnowballDto) - @ApiProperty({ - type: [DecorationSnowballDto], - description: '데코오브젝트들이 들어있는 배열' - }) - readonly deco_list: DecorationSnowballDto[]; - @IsNumber() @IsNotEmpty() @ApiProperty({ type: Number, description: '유저의 id' }) diff --git a/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts b/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts deleted file mode 100644 index fda9919..0000000 --- a/back/src/modules/snowball/dto/request/req-update-decoration.dto.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { IsNotEmpty, ValidateNested } from '@nestjs/class-validator'; -import { Type } from '@nestjs/class-transformer'; -import { ApiProperty } from '@nestjs/swagger'; -import { DecorationSnowballDto } from '../decoration-snowball.dto'; - -export class ReqUpdateSnowballDecoDto { - @IsNotEmpty() - @ValidateNested({ each: true }) - @Type(() => DecorationSnowballDto) - @ApiProperty({ - type: [DecorationSnowballDto], - description: '데코오브젝트들이 들어있는 배열' - }) - readonly deco_list: DecorationSnowballDto[]; -} diff --git a/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts b/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts deleted file mode 100644 index afea3eb..0000000 --- a/back/src/modules/snowball/dto/response/res-update-decoration.dto.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { IsNotEmpty, IsNumber, ValidateNested } from '@nestjs/class-validator'; -import { Type } from '@nestjs/class-transformer'; -import { ApiProperty } from '@nestjs/swagger'; -import { DecorationSnowballDto } from '../decoration-snowball.dto'; - -export class ResUpdateSnowballDecoDto { - @IsNotEmpty() - @IsNumber() - @ApiProperty({ type: Number, description: '스노우볼 id' }) - readonly snowball_id: number; - - @IsNotEmpty() - @ValidateNested({ each: true }) - @Type(() => DecorationSnowballDto) - @ApiProperty({ - type: [DecorationSnowballDto], - description: '변경된 데코오브젝트들이 들어있는 배열' - }) - readonly deco_list: DecorationSnowballDto[]; -} diff --git a/back/src/modules/snowball/dto/snowball.dto.ts b/back/src/modules/snowball/dto/snowball.dto.ts index daee549..47a3ada 100644 --- a/back/src/modules/snowball/dto/snowball.dto.ts +++ b/back/src/modules/snowball/dto/snowball.dto.ts @@ -3,11 +3,11 @@ import { IsBoolean, IsNumber, IsNotEmpty, - ValidateNested + ValidateNested, + IsHexColor } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; -import { DecorationSnowballDto } from '../../snowball/dto/decoration-snowball.dto'; import { MessageDto } from '../../message/dto/message.dto'; export class SnowballDto { @@ -29,14 +29,18 @@ export class SnowballDto { }) readonly is_message_private: boolean; + @IsNumber() @IsNotEmpty() - @ValidateNested({ each: true }) - @Type(() => DecorationSnowballDto) @ApiProperty({ - type: [DecorationSnowballDto], - description: '데코오브젝트들이 들어있는 리스트' + type: Number, + description: '스노우볼 메인 장식 데코레이션 id' }) - readonly deco_list: DecorationSnowballDto[]; + readonly main_decoration_id: number; + + @IsHexColor() + @IsNotEmpty() + @ApiProperty({ type: String, description: '스노우볼 메인 장식 색상' }) + readonly main_decoration_color: string; @ValidateNested({ each: true }) @Type(() => MessageDto) diff --git a/back/src/modules/snowball/dto/update-main-decoration.dto.ts b/back/src/modules/snowball/dto/update-main-decoration.dto.ts new file mode 100644 index 0000000..e5e173a --- /dev/null +++ b/back/src/modules/snowball/dto/update-main-decoration.dto.ts @@ -0,0 +1,19 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsNumber, IsNotEmpty, IsHexColor } from 'class-validator'; + +export class UpdateMainDecoDto { + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '스노우볼 id' }) + readonly snowball_id: number; + + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '장식 id' }) + readonly main_decoration_id: number; + + @IsHexColor() + @IsNotEmpty() + @ApiProperty({ type: String, description: '장식 색상', example: '#FFFFFF' }) + readonly main_decoration_color: string; +} diff --git a/back/src/modules/snowball/entity/snowball-decoration.entity.ts b/back/src/modules/snowball/entity/snowball-decoration.entity.ts deleted file mode 100644 index 9b25028..0000000 --- a/back/src/modules/snowball/entity/snowball-decoration.entity.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { - Entity, - Column, - PrimaryGeneratedColumn, - ManyToOne, - JoinColumn -} from 'typeorm'; -import { SnowballEntity } from './snowball.entity'; - -@Entity({ name: 'snowball_decoration' }) -export class SnowballDecorationEntity { - @PrimaryGeneratedColumn() - id: number; - - @Column() - snowball_id: number; - - @Column() - decoration_id: number; - - @Column({ length: 7 }) - decoration_color: string; - - @Column() - location: number; - - @ManyToOne(() => SnowballEntity, snowball => snowball.decorations) - @JoinColumn({ name: 'snowball_id' }) - snowball: SnowballEntity; -} diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index a85163b..5e1b473 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -8,7 +8,6 @@ import { JoinColumn } from 'typeorm'; import { UserEntity } from '../../auth/entity/user.entity'; -import { SnowballDecorationEntity } from './snowball-decoration.entity'; import { MessageEntity } from '../../message/entity/message.entity'; @Entity({ name: 'snowball' }) @@ -25,6 +24,12 @@ export class SnowballEntity { @CreateDateColumn() created_at: Date; + @Column() + main_decoration_id: number; + + @Column() + main_decoration_color: string; + @CreateDateColumn({ nullable: true, default: null }) message_private: Date | null; @@ -34,7 +39,4 @@ export class SnowballEntity { @OneToMany(() => MessageEntity, message => message.snowball) messages: MessageEntity[]; - - @OneToMany(() => SnowballDecorationEntity, decoration => decoration.snowball) - decorations: SnowballDecorationEntity[]; } diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index 554afdd..2ab0ae9 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -22,9 +22,8 @@ import { ReqCreateSnowballDto } from './dto/request/req-create-snowball.dto'; import { ReqUpdateSnowballDto } from './dto/request/req-update-snowball.dto'; import { SnowballDto } from './dto/snowball.dto'; import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; -import { ReqUpdateSnowballDecoDto } from './dto/request/req-update-decoration.dto'; -import { ResUpdateSnowballDecoDto } from './dto/response/res-update-decoration.dto'; import { JWTGuard } from '../auth/auth.guard'; +import { UpdateMainDecoDto } from './dto/update-main-decoration.dto'; @ApiTags('Snowball API') @UseGuards(JWTGuard) @@ -55,29 +54,6 @@ export class SnowballController { return snowball; } - @Put('/:snowball_id/decoration') - @HttpCode(200) - @ApiResponse({ - status: 200, - description: '스노우볼 데코레이션 업데이트 성공', - type: ResUpdateSnowballDecoDto - }) - @ApiOperation({ - summary: '스노우볼 데코레이션 업데이트 API', - description: '스노우볼의 데코레이션들을 업데이트 해줍니다.' - }) - @ApiBody({ type: ReqUpdateSnowballDecoDto }) - updateSnowballDecor( - @Param('snowball_id') snowball_id: number, - @Body() updateSnowballDecoDto: ReqUpdateSnowballDecoDto - ) { - const snowballDecoration = this.snowballService.updateSnowballDeco( - updateSnowballDecoDto, - snowball_id - ); - return snowballDecoration; - } - @Put('/:snowball_id') @HttpCode(200) @ApiResponse({ @@ -116,4 +92,26 @@ export class SnowballController { const snowball = await this.snowballService.getSnowball(snowball_id); return snowball; } + + @Put('/:snowball_id/decoration') + @ApiResponse({ + status: 200, + description: '스노우볼 메인 장식 업데이트 성공', + type: UpdateMainDecoDto + }) + @ApiOperation({ + summary: '스노우볼 메인 장식 업데이트 API', + description: '스노우볼의 메인 장식을 업데이트 합니다.' + }) + @ApiBody({ type: UpdateMainDecoDto }) + async updateMainDecoration( + @Param('snowball_id') snowball_id: number, + @Body() updateMainDecoDto: UpdateMainDecoDto + ) { + const snowball = await this.snowballService.updateMainDecoration( + updateMainDecoDto, + snowball_id + ); + return snowball; + } } diff --git a/back/src/modules/snowball/snowball.module.ts b/back/src/modules/snowball/snowball.module.ts index 04dd4c6..c366d92 100644 --- a/back/src/modules/snowball/snowball.module.ts +++ b/back/src/modules/snowball/snowball.module.ts @@ -5,16 +5,11 @@ import { MessageModule } from '../message/message.module'; import { TypeOrmModule } from '@nestjs/typeorm'; import { SnowballEntity } from './entity/snowball.entity'; import { MessageEntity } from '../message/entity/message.entity'; -import { SnowballDecorationEntity } from './entity/snowball-decoration.entity'; import { AuthModule } from '../auth/auth.module'; @Module({ imports: [ - TypeOrmModule.forFeature([ - SnowballEntity, - MessageEntity, - SnowballDecorationEntity - ]), + TypeOrmModule.forFeature([SnowballEntity, MessageEntity]), MessageModule, AuthModule ], diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 9b0d74c..3da6815 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -5,19 +5,14 @@ import { SnowballEntity } from './entity/snowball.entity'; import { ReqCreateSnowballDto } from './dto/request/req-create-snowball.dto'; import { ReqUpdateSnowballDto } from './dto/request/req-update-snowball.dto'; import { SnowballDto } from './dto/snowball.dto'; -import { SnowballDecorationEntity } from './entity/snowball-decoration.entity'; -import { DecorationSnowballDto } from './dto/decoration-snowball.dto'; -import { ResUpdateSnowballDecoDto } from './dto/response/res-update-decoration.dto'; -import { ReqUpdateSnowballDecoDto } from './dto/request/req-update-decoration.dto'; import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; +import { UpdateMainDecoDto } from './dto/update-main-decoration.dto'; @Injectable() export class SnowballService { constructor( @InjectRepository(SnowballEntity) - private readonly snowballRepository: Repository, - @InjectRepository(SnowballDecorationEntity) - private readonly decorationRepository: Repository + private readonly snowballRepository: Repository ) {} async createSnowball( @@ -31,62 +26,17 @@ export class SnowballService { }); const savedSnowball = await this.snowballRepository.save(snowball); - // To Do: bulk insert로 변경 & 반환값으로 Dto - const decoList = createSnowballDto.deco_list; - for (const deco of decoList) { - await this.createDecoration(savedSnowball.id, deco); - } const combinedSnowballDto: SnowballDto = { id: savedSnowball.id, title: savedSnowball.title, + main_decoration_color: savedSnowball.main_decoration_color, + main_decoration_id: savedSnowball.main_decoration_id, is_message_private: savedSnowball.message_private === null ? false : true, - deco_list: decoList, message_list: [] }; return combinedSnowballDto; } - async createDecoration( - snowball_id: number, - deco: DecorationSnowballDto - ): Promise { - const decoration = this.decorationRepository.create({ - ...deco, - snowball_id - }); - const savedDecoration = await this.decorationRepository.save(decoration); - const decorationDto: DecorationSnowballDto = { - decoration_id: savedDecoration.decoration_id, - decoration_color: savedDecoration.decoration_color, - location: savedDecoration.location - }; - return decorationDto; - } - - async updateSnowballDeco( - updateSnowballDecoDto: ReqUpdateSnowballDecoDto, - snowball_id: number - ): Promise { - const { deco_list } = updateSnowballDecoDto; - - // Delete all decorations - await this.decorationRepository.delete({ - snowball_id - }); - - // Create new decorations - for (const deco of deco_list) { - await this.createDecoration(snowball_id, deco); - } - - // Return the updated snowball - const resSnowball: ResUpdateSnowballDecoDto = { - snowball_id, - deco_list - }; - return resSnowball; - } - async updateSnowball( updateSnowballDto: ReqUpdateSnowballDto, snowball_id: number @@ -120,8 +70,7 @@ export class SnowballService { const snowball = await this.snowballRepository.findOne({ where: { id: snowball_id }, relations: { - messages: true, - decorations: true + messages: true } }); if (!snowball) { @@ -132,7 +81,6 @@ export class SnowballService { id: snowball.id, title: snowball.title, is_message_private: snowball.message_private ? true : false, - deco_list: snowball.decorations, message_list: snowball.messages.map(message => ({ id: message.id, decoration_id: message.decoration_id, @@ -141,10 +89,35 @@ export class SnowballService { sender: message.sender, opened: message.opened, created: message.created, - letter_id: message.letter_id - })) + letter_id: message.letter_id, + location: message.location + })), + main_decoration_id: 0, + main_decoration_color: '' }; return resSnowball; } + + async updateMainDecoration( + updateMainDecoDto: UpdateMainDecoDto, + snowball_id: number + ): Promise { + const { main_decoration_id, main_decoration_color } = updateMainDecoDto; + + const updateResult = await this.snowballRepository + .createQueryBuilder() + .update(SnowballEntity) + .set({ + main_decoration_id: main_decoration_id, + main_decoration_color: main_decoration_color + }) + .where('id = :id', { id: snowball_id }) + .execute(); + if (!updateResult.affected) { + throw new NotFoundException('업데이트할 스노우볼이 존재하지 않습니다.'); + } + + return updateMainDecoDto; + } } From 17b2f696c53082e784e523a6c1efe75d64c9d84f Mon Sep 17 00:00:00 2001 From: peageon Date: Tue, 28 Nov 2023 03:20:08 +0900 Subject: [PATCH 113/185] =?UTF-8?q?fix:=20BE/main=EC=97=90=20PR=EC=98=AC?= =?UTF-8?q?=EB=A6=B4=EB=95=8C=20=EC=9B=8C=ED=81=AC=ED=94=8C=EB=A1=9C?= =?UTF-8?q?=EC=9A=B0=20=EC=9E=91=EB=8F=99=20=EC=95=88=EB=90=98=EA=B2=8C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/BackEnd.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/BackEnd.yml b/.github/workflows/BackEnd.yml index e4f1783..f716f48 100644 --- a/.github/workflows/BackEnd.yml +++ b/.github/workflows/BackEnd.yml @@ -6,8 +6,6 @@ name: Node.js CI on: push: branches: ["BE/main"] - pull_request: - branches: ["BE/main"] jobs: # test: From 186307d8f47ae62838310b8286156e40d8ba2e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 28 Nov 2023 09:29:53 +0900 Subject: [PATCH 114/185] =?UTF-8?q?feat:=20=EB=AA=A8=EB=93=88=20=EA=B4=80?= =?UTF-8?q?=EA=B3=84=20=EC=A0=95=EB=A6=BD=20&=20user=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/app.module.ts | 16 +- back/src/modules/auth/auth.controller.ts | 68 +++---- back/src/modules/auth/auth.guard.ts | 6 +- back/src/modules/auth/auth.module.ts | 12 +- back/src/modules/auth/auth.service.ts | 175 ++++-------------- .../modules/auth/dto/response/res-info.dto.ts | 28 --- .../auth/strategy/google-auth.strategy.ts | 2 +- .../modules/message/entity/message.entity.ts | 2 +- .../src/modules/message/message.controller.ts | 4 +- back/src/modules/message/message.module.ts | 12 +- back/src/modules/message/message.service.ts | 36 +--- .../snowball/entity/snowball.entity.ts | 2 +- back/src/modules/snowball/snowball.module.ts | 9 +- back/src/modules/snowball/snowball.service.ts | 41 ++++ .../dto/response/res-info.dto.ts} | 2 +- .../modules/{auth => user}/dto/user.dto.ts | 2 +- .../{auth => user}/entity/user.entity.ts | 0 back/src/modules/user/user.controller.ts | 50 +++++ back/src/modules/user/user.module.ts | 21 +++ back/src/modules/user/user.service.ts | 64 +++++++ 20 files changed, 290 insertions(+), 262 deletions(-) delete mode 100644 back/src/modules/auth/dto/response/res-info.dto.ts rename back/src/modules/{auth/dto/response/res-visit-info.do.ts => user/dto/response/res-info.dto.ts} (93%) rename back/src/modules/{auth => user}/dto/user.dto.ts (97%) rename back/src/modules/{auth => user}/entity/user.entity.ts (100%) create mode 100644 back/src/modules/user/user.controller.ts create mode 100644 back/src/modules/user/user.module.ts create mode 100644 back/src/modules/user/user.service.ts diff --git a/back/src/app.module.ts b/back/src/app.module.ts index 0be1f26..ece5421 100644 --- a/back/src/app.module.ts +++ b/back/src/app.module.ts @@ -3,25 +3,17 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { AuthModule } from './modules/auth/auth.module'; -import { SnowballModule } from './modules/snowball/snowball.module'; import typeOrmConfig from './config/ormconfig'; -import { ConfigModule } from '@nestjs/config'; -import { ConfigService } from '@nestjs/config'; import { JwtModule } from '@nestjs/jwt'; +import { UserModule } from './modules/user/user.module'; @Module({ imports: [ TypeOrmModule.forRoot(typeOrmConfig), - ConfigModule.forRoot({ isGlobal: true }), + UserModule, AuthModule, - SnowballModule, - JwtModule.registerAsync({ - global: true, - inject: [ConfigService], - useFactory: (config: ConfigService) => ({ - secret: config.get('JWT_SECRET'), - signOptions: { expiresIn: '300s' } - }) + JwtModule.register({ + global: true }) ], controllers: [AppController], diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index 3b57852..8e8fd2b 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -1,9 +1,9 @@ -import { Controller, Get, Req, Param, UseGuards } from '@nestjs/common'; +import { Controller, Get, Req, Res, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; -import { ResInfoDto } from './dto/response/res-info.dto'; +import { ResInfoDto } from '../user/dto/response/res-info.dto'; import { AuthService } from './auth.service'; -import { ResVisitInfoDto } from './dto/response/res-visit-info.do'; +import { payload } from './auth.service'; @ApiTags('Oauth API') @Controller('auth') @@ -37,10 +37,17 @@ export class AuthController { status: 500, description: 'Internal Server Error' }) - async googleLoginCallback(@Req() req): Promise { - const userInfo = req.user; - const result = this.authService.createUserInfo(userInfo); - return result; + async googleLoginCallback(@Req() req: any, @Res() res: any): Promise { + const payload: payload = await this.authService.getUserInfo(req.user); + const { accessToken, refreshToken } = + this.authService.generateJwtToken(payload); + res.setHeader('Authorization', `Bearer ${accessToken}`); + // To DO: refresh token db에 저장 & 클라이언트에는 index만 저장? + res.cookie('refresh_token', refreshToken, { + httpOnly: true, + maxAge: `${process.env.JWT_REFRESH_AGE}` + }); + res.redirect(`${process.env.OAUTH_REDIRECT_URL}`); } @Get('naver') @@ -71,10 +78,17 @@ export class AuthController { status: 500, description: 'Internal Server Error' }) - async naverLoginCallBack(@Req() req): Promise { - const userInfo = req.user; - const result = this.authService.createUserInfo(userInfo); - return result; + async naverLoginCallBack(@Req() req: any, @Res() res: any): Promise { + const payload: payload = await this.authService.getUserInfo(req.user); + const { accessToken, refreshToken } = + this.authService.generateJwtToken(payload); + res.setHeader('Authorization', `Bearer ${accessToken}`); + // To DO: refresh token db에 저장 & 클라이언트에는 index만 저장? + res.cookie('refresh_token', refreshToken, { + httpOnly: true, + maxAge: `${process.env.JWT_REFRESH_AGE}` + }); + res.redirect(`${process.env.OAUTH_REDIRECT_URL}`); } @Get('kakao') @@ -105,26 +119,16 @@ export class AuthController { status: 500, description: 'Internal Server Error' }) - async kakaoLoginCallBack(@Req() req): Promise { - const userInfo = req.user; - const result = this.authService.createUserInfo(userInfo); - return result; - } - - @Get('visit/:user_id') - @ApiOperation({ - summary: '방문자 유저 조회 API', - description: '방문자가 접속한 유저의 정보를 반환합니다' - }) - @ApiResponse({ - status: 500, - description: 'Internal Server Error', - type: ResVisitInfoDto - }) - async createVisitInfo( - @Param('user_id') user_id: string - ): Promise { - const result = this.authService.createVisitInfo(user_id); - return result; + async kakaoLoginCallBack(@Req() req: any, @Res() res: any): Promise { + const payload: payload = await this.authService.getUserInfo(req.user); + const { accessToken, refreshToken } = + this.authService.generateJwtToken(payload); + res.setHeader('Authorization', `Bearer ${accessToken}`); + // To DO: refresh token db에 저장 & 클라이언트에는 index만 저장? + res.cookie('refresh_token', refreshToken, { + httpOnly: true, + maxAge: `${process.env.JWT_REFRESH_AGE}` + }); + res.redirect(`${process.env.OAUTH_REDIRECT_URL}`); } } diff --git a/back/src/modules/auth/auth.guard.ts b/back/src/modules/auth/auth.guard.ts index 69d532b..40dc7e5 100644 --- a/back/src/modules/auth/auth.guard.ts +++ b/back/src/modules/auth/auth.guard.ts @@ -20,9 +20,11 @@ export class JWTGuard implements CanActivate { } try { const payload = await this.jwtService.verify(token, { - secret: process.env.JWT_SECRET + secret: process.env.JWT_ACCESS_SECRET }); - request['id'] = payload.user_pk; + request['id'] = payload.id; + request['name'] = payload.name; + request['user_id'] = payload.user_id; } catch { throw new UnauthorizedException(); } diff --git a/back/src/modules/auth/auth.module.ts b/back/src/modules/auth/auth.module.ts index 7ef8005..a64c23e 100644 --- a/back/src/modules/auth/auth.module.ts +++ b/back/src/modules/auth/auth.module.ts @@ -5,24 +5,18 @@ import { KakaoAuthStrategy } from './strategy/kakao-auth.strategy'; import { AuthController } from './auth.controller'; import { PassportModule } from '@nestjs/passport'; import { AuthService } from './auth.service'; -import { SnowballService } from '../snowball/snowball.service'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { SnowballEntity } from '../snowball/entity/snowball.entity'; -import { UserEntity } from './entity/user.entity'; +import { UserEntity } from '../user/entity/user.entity'; import { JWTGuard } from './auth.guard'; -import { MessageEntity } from '../message/entity/message.entity'; +import { JwtModule } from '@nestjs/jwt'; @Module({ - imports: [ - TypeOrmModule.forFeature([UserEntity, SnowballEntity, MessageEntity]), - PassportModule - ], + imports: [TypeOrmModule.forFeature([UserEntity]), PassportModule, JwtModule], providers: [ GoogleAuthStrategy, NaverAuthStrategy, KakaoAuthStrategy, AuthService, - SnowballService, JWTGuard ], controllers: [AuthController], diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index 13ce9c4..43fb0b3 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -1,157 +1,62 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; -import { ResInfoDto } from './dto/response/res-info.dto'; -import { UserDto } from './dto/user.dto'; -import { SnowballDto } from '../snowball/dto/snowball.dto'; +import { Injectable } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; -import { SnowballService } from '../snowball/snowball.service'; import { InjectRepository } from '@nestjs/typeorm'; +import { UserEntity } from '../user/entity/user.entity'; import { Repository } from 'typeorm'; -import { UserEntity } from './entity/user.entity'; -import { SnowballEntity } from '../snowball/entity/snowball.entity'; -import { ResVisitInfoDto } from './dto/response/res-visit-info.do'; -import { MessageEntity } from '../message/entity/message.entity'; -interface SnowballInfo { - snowball_count: number; - message_count: number; - snowball_list: number[]; - main_snowball_id: number | null; + +export interface payload { + id: number; + name: string; + user_id: string; } @Injectable() export class AuthService { constructor( - @InjectRepository(UserEntity) - private readonly UserRepository: Repository, - @InjectRepository(SnowballEntity) - private readonly SnowballRepository: Repository, - @InjectRepository(MessageEntity) - private readonly MessageRepository: Repository, private readonly jwtService: JwtService, - private readonly snowballService: SnowballService + @InjectRepository(UserEntity) + private readonly UserRepository: Repository ) {} - async createUserInfo(user: any): Promise { - const { user_pk, is_existed } = await this.getUserPk(user); - const jwt_token = this.generateJwtToken(user_pk); - const userDto: UserDto = await this.createUserDto( - user_pk, - user.name, - user.id, - is_existed - ); - const mainSnowballDto = await this.getMainSnowballDto(userDto); - - const resInfoDto: ResInfoDto = { - jwt_token, - user: userDto, - main_snowball: mainSnowballDto - }; - - return resInfoDto; - } - - async createVisitInfo(user_id: string): Promise { - const user = await this.UserRepository.findOne({ - where: { user_id: user_id } - }); - if (!user) throw new NotFoundException('해당 유저를 찾을 수 없습니다.'); - const userDto: UserDto = await this.createUserDto( - user.id, - user.username, - user.user_id, - true - ); - const mainSnowballDto = await this.getMainSnowballDto(userDto); - - const resVisitInfo: ResVisitInfoDto = { - user: userDto, - main_snowball: mainSnowballDto - }; - return resVisitInfo; - } - - async createUserDto( - user_pk: number, - username: string, - user_id: string, - is_existed: boolean - ): Promise { - const { snowball_count, message_count, snowball_list, main_snowball_id } = - await this.getSnowballInfo(user_pk, is_existed); - - const userDto: UserDto = { - id: user_pk, - name: username, - auth_id: user_id, - snowball_count: snowball_count, - main_snowball_id: main_snowball_id, - snowball_list: snowball_list, - message_count: message_count - }; - return userDto; - } - - async getUserPk( - user: any - ): Promise<{ user_pk: number; is_existed: boolean }> { + async getUserInfo(user: any): Promise { const exisitingUser = await this.UserRepository.findOne({ - where: { user_id: user.id } + where: { user_id: user.user_id } }); if (exisitingUser) { - return { user_pk: exisitingUser.id, is_existed: true }; - } else { - const newUser: UserEntity = this.UserRepository.create({ - user_id: user.id, - username: user.name, - provider: user.provider, - created_at: new Date() - }); - - const saveduser = await this.UserRepository.insert(newUser); - const pk = saveduser.identifiers.pop().id; - return { user_pk: pk, is_existed: false }; - } - } - - async getMainSnowballDto(userDto: UserDto): Promise { - if (!userDto.main_snowball_id) { - return null; - } else { - return await this.snowballService.getSnowball(userDto.main_snowball_id); - } - } - - async getSnowballInfo( - user_pk: number, - is_existed: boolean - ): Promise { - const snowballs = await this.SnowballRepository.findAndCount({ - where: { user_id: user_pk } - }); - - if (is_existed && snowballs[0].length > 0) { - const snowball_list = snowballs[0].map(snowball => snowball.id); return { - snowball_count: snowballs[1], - message_count: await this.getMessageCount(user_pk), - snowball_list, - main_snowball_id: snowballs[0][0].id + id: exisitingUser.id, + name: exisitingUser.username, + user_id: exisitingUser.user_id }; } else { - return { - snowball_count: 0, - message_count: 0, - snowball_list: [], - main_snowball_id: null - }; + return await this.signUp(user); } } - async getMessageCount(user_pk: number): Promise { - return this.MessageRepository.count({ where: { user: { id: user_pk } } }); - } + async signUp(user: any): Promise { + const newUser: UserEntity = this.UserRepository.create({ + user_id: user.user_id, + username: user.name, + provider: user.provider, + created_at: new Date() + }); + const saveduser = await this.UserRepository.insert(newUser); + const id = saveduser.identifiers.pop().id; + return { id: id, name: user.name, user_id: user.user_id }; + } + + generateJwtToken(payload: payload): { + accessToken: string; + refreshToken: string; + } { + const accessToken = this.jwtService.sign(payload, { + expiresIn: `${process.env.JWT_ACCESS_AGE}`, + secret: `${process.env.JWT_ACCESS_SECRET}` + }); - generateJwtToken(user_pk: any): string { - const payload = { user_pk: user_pk }; - return this.jwtService.sign(payload); + const refreshToken = this.jwtService.sign(payload, { + expiresIn: `${process.env.JWT_REFRESH_AGE}`, + secret: `${process.env.JWT_REFRESH_SECRET}` + }); + return { accessToken, refreshToken }; } } diff --git a/back/src/modules/auth/dto/response/res-info.dto.ts b/back/src/modules/auth/dto/response/res-info.dto.ts deleted file mode 100644 index e42e86f..0000000 --- a/back/src/modules/auth/dto/response/res-info.dto.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { IsString, IsNotEmpty } from '@nestjs/class-validator'; -import { ApiProperty } from '@nestjs/swagger'; -import { UserDto } from '../user.dto'; -import { SnowballDto } from '../../../snowball/dto/snowball.dto'; - -export class ResInfoDto { - @IsNotEmpty() - @IsString() - @ApiProperty({ - type: String, - description: 'JWT 타입의 유저 토큰' - }) - readonly jwt_token: string; - - @IsNotEmpty() - @ApiProperty({ - type: UserDto, - description: '사용자 정보 ' - }) - readonly user: UserDto; - - @IsNotEmpty() - @ApiProperty({ - type: SnowballDto, - description: '메인 스노우볼 정보' - }) - readonly main_snowball: SnowballDto | null; -} diff --git a/back/src/modules/auth/strategy/google-auth.strategy.ts b/back/src/modules/auth/strategy/google-auth.strategy.ts index 6c8bf4f..34dce81 100644 --- a/back/src/modules/auth/strategy/google-auth.strategy.ts +++ b/back/src/modules/auth/strategy/google-auth.strategy.ts @@ -26,7 +26,7 @@ export class GoogleAuthStrategy extends PassportStrategy(Strategy, 'google') { ) { try { const user = { - id: profile.id, + user_id: profile.id, name: profile.displayName, provider: profile.provider, accessToken, diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 0856f59..9d11991 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -7,7 +7,7 @@ import { JoinColumn } from 'typeorm'; import { SnowballEntity } from 'src/modules/snowball/entity/snowball.entity'; -import { UserEntity } from 'src/modules/auth/entity/user.entity'; +import { UserEntity } from 'src/modules/user/entity/user.entity'; @Entity({ synchronize: true, name: 'message' }) export class MessageEntity { diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 9c98e28..378a824 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -36,7 +36,7 @@ import { ReqUpdateMessageLocationDto } from './dto/request/req-update-message-lo export class MessageController { constructor(private readonly messageService: MessageService) {} - @Post('/:snowball_id') + @Post('/:user_id/:snowball_id') @HttpCode(201) @ApiOperation({ summary: '메세지 생성 API', @@ -53,11 +53,13 @@ export class MessageController { description: 'Insert Fail' }) async createMessage( + @Param('user_id') user_id: number, @Param('snowball_id') snowball_id: number, @Body() createMessageDto: ReqCreateMessageDto ): Promise { const resCreateMessage = await this.messageService.createMessage( createMessageDto, + user_id, snowball_id ); return resCreateMessage; diff --git a/back/src/modules/message/message.module.ts b/back/src/modules/message/message.module.ts index dd3c0bb..62d9847 100644 --- a/back/src/modules/message/message.module.ts +++ b/back/src/modules/message/message.module.ts @@ -3,15 +3,11 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { MessageController } from './message.controller'; import { MessageService } from './message.service'; import { MessageEntity } from './entity/message.entity'; -import { UserEntity } from '../auth/entity/user.entity'; -import { SnowballEntity } from '../snowball/entity/snowball.entity'; -import { AuthModule } from '../auth/auth.module'; +import { JWTGuard } from '../auth/auth.guard'; @Module({ - imports: [ - TypeOrmModule.forFeature([UserEntity, SnowballEntity, MessageEntity]), - AuthModule - ], + imports: [TypeOrmModule.forFeature([MessageEntity])], controllers: [MessageController], - providers: [MessageService] + providers: [MessageService, JWTGuard], + exports: [MessageService, TypeOrmModule] }) export class MessageModule {} diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 121ebbb..70ac9cc 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -10,28 +10,22 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; import { MessageEntity } from './entity/message.entity'; -import { UserEntity } from '../auth/entity/user.entity'; import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; import { MessageDto } from './dto/message.dto'; -import { SnowballEntity } from '../snowball/entity/snowball.entity'; import { ReqUpdateMessageDecorationDto } from './dto/request/req-update-message-decoration.dto'; import { ReqUpdateMessageLocationDto } from './dto/request/req-update-message-location.dto'; @Injectable() export class MessageService { constructor( - @InjectRepository(UserEntity) - private readonly userRepository: Repository, @InjectRepository(MessageEntity) - private readonly messageRepository: Repository, - @InjectRepository(SnowballEntity) - private readonly snowballRepository: Repository + private readonly messageRepository: Repository ) {} async createMessage( createMessageDto: ReqCreateMessageDto, + user_id: number, snowball_id: number ): Promise { - const user_id = await this.getUserId(snowball_id); const messageEntity = this.messageRepository.create({ user_id: user_id, snowball_id: snowball_id, @@ -79,21 +73,13 @@ export class MessageService { async getAllMessages(user_id: number): Promise { //To Do: query builder로 개선하기 - const user = await this.userRepository.findOne({ - where: { id: user_id }, - relations: { - snowballs: { - messages: true - } - } + const messages: MessageEntity[] = await this.messageRepository.find({ + where: { user_id: user_id, is_deleted: false } }); - if (!user) { + if (!messages) { throw new NotFoundException(`User with id ${user_id} not found`); } - const messages: MessageEntity[] = user.snowballs - .flatMap(snowball => snowball.messages) - .filter(message => !message.is_deleted); const messagesDto: MessageDto[] = messages.map(message => { const { id, @@ -118,6 +104,7 @@ export class MessageService { location }; }); + // const messagesDto: MessageDto[] = plainToClass(MessageDto, messages); return messagesDto; } @@ -144,13 +131,6 @@ export class MessageService { }; } - async getUserId(snowball_id: number): Promise { - const snowball = await this.snowballRepository.findOne({ - where: { id: snowball_id } - }); - return snowball.user_id; - } - async updateMessageDecoration( message_id: number, updateMessageDecorationDto: ReqUpdateMessageDecorationDto @@ -196,4 +176,8 @@ export class MessageService { } return updateResult.raw[0] as MessageDto; } + + async getMessageCount(user_pk: number): Promise { + return this.messageRepository.count({ where: { user: { id: user_pk } } }); + } } diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index 5e1b473..7117e93 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -7,7 +7,7 @@ import { OneToMany, JoinColumn } from 'typeorm'; -import { UserEntity } from '../../auth/entity/user.entity'; +import { UserEntity } from '../../user/entity/user.entity'; import { MessageEntity } from '../../message/entity/message.entity'; @Entity({ name: 'snowball' }) diff --git a/back/src/modules/snowball/snowball.module.ts b/back/src/modules/snowball/snowball.module.ts index c366d92..2a4a52e 100644 --- a/back/src/modules/snowball/snowball.module.ts +++ b/back/src/modules/snowball/snowball.module.ts @@ -4,16 +4,17 @@ import { SnowballService } from './snowball.service'; import { MessageModule } from '../message/message.module'; import { TypeOrmModule } from '@nestjs/typeorm'; import { SnowballEntity } from './entity/snowball.entity'; +import { JWTGuard } from '../auth/auth.guard'; import { MessageEntity } from '../message/entity/message.entity'; -import { AuthModule } from '../auth/auth.module'; +import { MessageService } from '../message/message.service'; @Module({ imports: [ TypeOrmModule.forFeature([SnowballEntity, MessageEntity]), - MessageModule, - AuthModule + MessageModule ], controllers: [SnowballController], - providers: [SnowballService] + providers: [SnowballService, MessageService, JWTGuard], + exports: [SnowballService, MessageService, TypeOrmModule] }) export class SnowballModule {} diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 3da6815..3bcfd05 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -7,10 +7,20 @@ import { ReqUpdateSnowballDto } from './dto/request/req-update-snowball.dto'; import { SnowballDto } from './dto/snowball.dto'; import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; import { UpdateMainDecoDto } from './dto/update-main-decoration.dto'; +import { UserDto } from '../user/dto/user.dto'; +import { MessageService } from '../message/message.service'; + +export interface SnowballInfo { + snowball_count: number; + message_count: number; + snowball_list: number[]; + main_snowball_id: number | null; +} @Injectable() export class SnowballService { constructor( + private readonly messageService: MessageService, @InjectRepository(SnowballEntity) private readonly snowballRepository: Repository ) {} @@ -120,4 +130,35 @@ export class SnowballService { return updateMainDecoDto; } + + async getMainSnowballDto(userDto: UserDto): Promise { + if (!userDto.main_snowball_id) { + return null; + } else { + return await this.getSnowball(userDto.main_snowball_id); + } + } + + async getSnowballInfo(user_pk: number): Promise { + const snowballs = await this.snowballRepository.findAndCount({ + where: { user_id: user_pk } + }); + + if (snowballs[0].length > 0) { + const snowball_list = snowballs[0].map(snowball => snowball.id); + return { + snowball_count: snowballs[1], + message_count: await this.messageService.getMessageCount(user_pk), + snowball_list, + main_snowball_id: snowballs[0][0].id + }; + } else { + return { + snowball_count: 0, + message_count: 0, + snowball_list: [], + main_snowball_id: null + }; + } + } } diff --git a/back/src/modules/auth/dto/response/res-visit-info.do.ts b/back/src/modules/user/dto/response/res-info.dto.ts similarity index 93% rename from back/src/modules/auth/dto/response/res-visit-info.do.ts rename to back/src/modules/user/dto/response/res-info.dto.ts index 4126459..0982d9c 100644 --- a/back/src/modules/auth/dto/response/res-visit-info.do.ts +++ b/back/src/modules/user/dto/response/res-info.dto.ts @@ -3,7 +3,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { UserDto } from '../user.dto'; import { SnowballDto } from '../../../snowball/dto/snowball.dto'; -export class ResVisitInfoDto { +export class ResInfoDto { @IsNotEmpty() @ApiProperty({ type: UserDto, diff --git a/back/src/modules/auth/dto/user.dto.ts b/back/src/modules/user/dto/user.dto.ts similarity index 97% rename from back/src/modules/auth/dto/user.dto.ts rename to back/src/modules/user/dto/user.dto.ts index bd74169..3517472 100644 --- a/back/src/modules/auth/dto/user.dto.ts +++ b/back/src/modules/user/dto/user.dto.ts @@ -15,7 +15,7 @@ export class UserDto { @IsString() @IsNotEmpty() @ApiProperty({ type: String, description: 'Oauth에서 주는 값' }) - readonly auth_id: string; + readonly user_id: string; @IsNumber() @IsNotEmpty() diff --git a/back/src/modules/auth/entity/user.entity.ts b/back/src/modules/user/entity/user.entity.ts similarity index 100% rename from back/src/modules/auth/entity/user.entity.ts rename to back/src/modules/user/entity/user.entity.ts diff --git a/back/src/modules/user/user.controller.ts b/back/src/modules/user/user.controller.ts new file mode 100644 index 0000000..b50dee3 --- /dev/null +++ b/back/src/modules/user/user.controller.ts @@ -0,0 +1,50 @@ +import { Controller, Get, UseGuards, Param, Req } from '@nestjs/common'; +import { JWTGuard } from '../auth/auth.guard'; +import { + ApiTags, + ApiOperation, + ApiResponse, + ApiBearerAuth +} from '@nestjs/swagger'; +import { UserService } from './user.service'; +import { ResInfoDto } from './dto/response/res-info.dto'; + +@ApiTags('User API') +@Controller('user') +export class UserController { + constructor(private readonly userService: UserService) {} + + @UseGuards(JWTGuard) + @ApiBearerAuth('jwt-token') + @Get() + @ApiOperation({ + summary: '사용자 유저 조회 API', + description: '사용자가 접속한 유저의 정보를 반환합니다' + }) + @ApiResponse({ + status: 200, + type: ResInfoDto + }) + async createUserInfo(@Req() req: any): Promise { + const result = this.userService.createUserInfo(req); + return result; + } + + @Get('/:user_id') + @ApiOperation({ + summary: '방문자 유저 조회 API', + description: '방문자가 접속한 유저의 정보를 반환합니다' + }) + @ApiResponse({ + status: 500, + description: 'Internal Server Error', + type: ResInfoDto + }) + async createVisitInfo( + @Param('user_id') user_id: string + ): Promise { + const user_pk = this.userService.getUserPk(user_id); + const result = this.userService.createUserInfo(user_pk); + return result; + } +} diff --git a/back/src/modules/user/user.module.ts b/back/src/modules/user/user.module.ts new file mode 100644 index 0000000..f2cb99c --- /dev/null +++ b/back/src/modules/user/user.module.ts @@ -0,0 +1,21 @@ +import { Module } from '@nestjs/common'; +import { UserService } from './user.service'; +import { UserController } from './user.controller'; +import { UserEntity } from './entity/user.entity'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { SnowballModule } from '../snowball/snowball.module'; +import { JWTGuard } from '../auth/auth.guard'; +import { SnowballEntity } from '../snowball/entity/snowball.entity'; +import { MessageEntity } from '../message/entity/message.entity'; +import { SnowballService } from '../snowball/snowball.service'; +import { MessageService } from '../message/message.service'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([UserEntity, SnowballEntity, MessageEntity]), + SnowballModule + ], + controllers: [UserController], + providers: [UserService, JWTGuard, SnowballService, MessageService] +}) +export class UserModule {} diff --git a/back/src/modules/user/user.service.ts b/back/src/modules/user/user.service.ts new file mode 100644 index 0000000..03feb38 --- /dev/null +++ b/back/src/modules/user/user.service.ts @@ -0,0 +1,64 @@ +import { Injectable, NotFoundException } from '@nestjs/common'; +import { UserEntity } from './entity/user.entity'; +import { Repository } from 'typeorm'; +import { InjectRepository } from '@nestjs/typeorm'; +import { ResInfoDto } from './dto/response/res-info.dto'; +import { UserDto } from './dto/user.dto'; +import { SnowballService } from '../snowball/snowball.service'; + +@Injectable() +export class UserService { + constructor( + private readonly snowballService: SnowballService, + @InjectRepository(UserEntity) + private readonly UserRepository: Repository + ) {} + + async getUserPk(user: any): Promise { + const exisitingUser = await this.UserRepository.findOne({ + where: { user_id: user.id } + }); + if (exisitingUser) { + return exisitingUser.id; + } else { + throw new NotFoundException('해당 유저를 찾을 수 없습니다.'); + } + } + + async createUserInfo(user: any): Promise { + const userDto: UserDto = await this.createUserDto( + user.id, + user.name, + user.user_id + ); + const mainSnowballDto = + await this.snowballService.getMainSnowballDto(userDto); + + const resInfoDto: ResInfoDto = { + user: userDto, + main_snowball: mainSnowballDto + }; + + return resInfoDto; + } + + async createUserDto( + id: number, + username: string, + user_id: string + ): Promise { + const { snowball_count, message_count, snowball_list, main_snowball_id } = + await this.snowballService.getSnowballInfo(id); + + const userDto: UserDto = { + id: id, + name: username, + user_id: user_id, + snowball_count: snowball_count, + main_snowball_id: main_snowball_id, + snowball_list: snowball_list, + message_count: message_count + }; + return userDto; + } +} From 555ee120dfe6f39566b3942bb9e592e8257e7c9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 28 Nov 2023 09:45:19 +0900 Subject: [PATCH 115/185] =?UTF-8?q?fix:=20maxAge=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.controller.ts | 7 ++++--- back/src/modules/auth/auth.service.ts | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index 8e8fd2b..8d2b79c 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -43,9 +43,10 @@ export class AuthController { this.authService.generateJwtToken(payload); res.setHeader('Authorization', `Bearer ${accessToken}`); // To DO: refresh token db에 저장 & 클라이언트에는 index만 저장? + console.log(process.env.JWT_ACCESS_AGE); res.cookie('refresh_token', refreshToken, { httpOnly: true, - maxAge: `${process.env.JWT_REFRESH_AGE}` + maxAge: parseInt(`${process.env.JWT_REFRESH_AGE}`) }); res.redirect(`${process.env.OAUTH_REDIRECT_URL}`); } @@ -86,7 +87,7 @@ export class AuthController { // To DO: refresh token db에 저장 & 클라이언트에는 index만 저장? res.cookie('refresh_token', refreshToken, { httpOnly: true, - maxAge: `${process.env.JWT_REFRESH_AGE}` + maxAge: parseInt(`${process.env.JWT_REFRESH_AGE}`) }); res.redirect(`${process.env.OAUTH_REDIRECT_URL}`); } @@ -127,7 +128,7 @@ export class AuthController { // To DO: refresh token db에 저장 & 클라이언트에는 index만 저장? res.cookie('refresh_token', refreshToken, { httpOnly: true, - maxAge: `${process.env.JWT_REFRESH_AGE}` + maxAge: parseInt(`${process.env.JWT_REFRESH_AGE}`) }); res.redirect(`${process.env.OAUTH_REDIRECT_URL}`); } diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index 43fb0b3..e39b8d0 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -49,12 +49,12 @@ export class AuthService { refreshToken: string; } { const accessToken = this.jwtService.sign(payload, { - expiresIn: `${process.env.JWT_ACCESS_AGE}`, + expiresIn: parseInt(`${process.env.JWT_ACCESS_AGE}`), secret: `${process.env.JWT_ACCESS_SECRET}` }); const refreshToken = this.jwtService.sign(payload, { - expiresIn: `${process.env.JWT_REFRESH_AGE}`, + expiresIn: parseInt(`${process.env.JWT_REFRESH_AGE}`), secret: `${process.env.JWT_REFRESH_SECRET}` }); return { accessToken, refreshToken }; From d3bdc2fc5c5187fb2f67225d97833d023eef0e72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 28 Nov 2023 10:17:26 +0900 Subject: [PATCH 116/185] =?UTF-8?q?feat:=20dto=20=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.controller.ts | 1 - back/src/modules/auth/auth.service.ts | 1 + back/src/modules/user/dto/user.dto.ts | 6 +++- back/src/modules/user/entity/user.entity.ts | 3 ++ back/src/modules/user/user.controller.ts | 33 +++++++++++++++++++-- back/src/modules/user/user.service.ts | 30 +++++++++++++++++-- 6 files changed, 68 insertions(+), 6 deletions(-) diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index 8d2b79c..3efc0ac 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -43,7 +43,6 @@ export class AuthController { this.authService.generateJwtToken(payload); res.setHeader('Authorization', `Bearer ${accessToken}`); // To DO: refresh token db에 저장 & 클라이언트에는 index만 저장? - console.log(process.env.JWT_ACCESS_AGE); res.cookie('refresh_token', refreshToken, { httpOnly: true, maxAge: parseInt(`${process.env.JWT_REFRESH_AGE}`) diff --git a/back/src/modules/auth/auth.service.ts b/back/src/modules/auth/auth.service.ts index e39b8d0..00988b2 100644 --- a/back/src/modules/auth/auth.service.ts +++ b/back/src/modules/auth/auth.service.ts @@ -36,6 +36,7 @@ export class AuthService { const newUser: UserEntity = this.UserRepository.create({ user_id: user.user_id, username: user.name, + nickname: null, provider: user.provider, created_at: new Date() }); diff --git a/back/src/modules/user/dto/user.dto.ts b/back/src/modules/user/dto/user.dto.ts index 3517472..d3a7871 100644 --- a/back/src/modules/user/dto/user.dto.ts +++ b/back/src/modules/user/dto/user.dto.ts @@ -10,7 +10,11 @@ export class UserDto { @IsString() @IsNotEmpty() @ApiProperty({ type: String, description: '사용자 이름' }) - readonly name: string; + readonly username: string; + + @IsString() + @ApiProperty({ type: String, description: '사용자 닉네임' }) + readonly nickname: string | null; @IsString() @IsNotEmpty() diff --git a/back/src/modules/user/entity/user.entity.ts b/back/src/modules/user/entity/user.entity.ts index 28f079c..3790b08 100644 --- a/back/src/modules/user/entity/user.entity.ts +++ b/back/src/modules/user/entity/user.entity.ts @@ -21,6 +21,9 @@ export class UserEntity { @Column({ length: 16 }) username: string; + @Column({ length: 16, default: null }) + nickname: string | null; + @Column({ length: 16 }) provider: string; diff --git a/back/src/modules/user/user.controller.ts b/back/src/modules/user/user.controller.ts index b50dee3..5073c6a 100644 --- a/back/src/modules/user/user.controller.ts +++ b/back/src/modules/user/user.controller.ts @@ -1,10 +1,19 @@ -import { Controller, Get, UseGuards, Param, Req } from '@nestjs/common'; +import { + Controller, + Get, + Body, + UseGuards, + Param, + Req, + Put +} from '@nestjs/common'; import { JWTGuard } from '../auth/auth.guard'; import { ApiTags, ApiOperation, ApiResponse, - ApiBearerAuth + ApiBearerAuth, + ApiBody } from '@nestjs/swagger'; import { UserService } from './user.service'; import { ResInfoDto } from './dto/response/res-info.dto'; @@ -47,4 +56,24 @@ export class UserController { const result = this.userService.createUserInfo(user_pk); return result; } + + @UseGuards(JWTGuard) + @ApiBearerAuth('jwt-token') + @Put('/nickname') + @ApiBody({ type: String }) + @ApiOperation({ + summary: '사용자 닉네임 변 경 API', + description: '사용자가 닉네임을 변경합니다' + }) + @ApiResponse({ + status: 200, + type: String + }) + async updateNickname( + @Req() req: any, + @Body() nickname: string + ): Promise { + const result = this.userService.updateNickname(req.id, nickname); + return result; + } } diff --git a/back/src/modules/user/user.service.ts b/back/src/modules/user/user.service.ts index 03feb38..9e1a845 100644 --- a/back/src/modules/user/user.service.ts +++ b/back/src/modules/user/user.service.ts @@ -25,6 +25,17 @@ export class UserService { } } + async getUserNickname(id: number): Promise { + const exisitingUser = await this.UserRepository.findOne({ + where: { id: id } + }); + if (exisitingUser) { + return exisitingUser.nickname; + } else { + throw new NotFoundException('해당 유저를 찾을 수 없습니다.'); + } + } + async createUserInfo(user: any): Promise { const userDto: UserDto = await this.createUserDto( user.id, @@ -49,10 +60,11 @@ export class UserService { ): Promise { const { snowball_count, message_count, snowball_list, main_snowball_id } = await this.snowballService.getSnowballInfo(id); - + const nickname = await this.getUserNickname(id); const userDto: UserDto = { id: id, - name: username, + username: username, + nickname: nickname, user_id: user_id, snowball_count: snowball_count, main_snowball_id: main_snowball_id, @@ -61,4 +73,18 @@ export class UserService { }; return userDto; } + + async updateNickname(id: number, nickname: string): Promise { + const updateResult = await this.UserRepository.createQueryBuilder() + .update(UserEntity) + .set({ + nickname: nickname + }) + .where('id = :id', { id: id }) + .execute(); + if (!updateResult.affected) { + throw new NotFoundException('업데이트할 유저가 존재하지 않습니다.'); + } + return 'test'; + } } From 4b69b84799dee4243e5f646a3561c0b18852d3f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 28 Nov 2023 10:25:22 +0900 Subject: [PATCH 117/185] =?UTF-8?q?feat:=20update=20nickname=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/user/dto/nickname.dto.ts | 8 ++++++++ back/src/modules/user/user.controller.ts | 10 ++++++---- back/src/modules/user/user.service.ts | 5 +++-- 3 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 back/src/modules/user/dto/nickname.dto.ts diff --git a/back/src/modules/user/dto/nickname.dto.ts b/back/src/modules/user/dto/nickname.dto.ts new file mode 100644 index 0000000..7f643f8 --- /dev/null +++ b/back/src/modules/user/dto/nickname.dto.ts @@ -0,0 +1,8 @@ +import { IsString } from '@nestjs/class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class NicknameDto { + @IsString() + @ApiProperty({ type: String, description: '사용자 닉네임' }) + readonly nickname: string | null; +} diff --git a/back/src/modules/user/user.controller.ts b/back/src/modules/user/user.controller.ts index 5073c6a..18f7947 100644 --- a/back/src/modules/user/user.controller.ts +++ b/back/src/modules/user/user.controller.ts @@ -17,6 +17,7 @@ import { } from '@nestjs/swagger'; import { UserService } from './user.service'; import { ResInfoDto } from './dto/response/res-info.dto'; +import { NicknameDto } from './dto/nickname.dto'; @ApiTags('User API') @Controller('user') @@ -60,19 +61,20 @@ export class UserController { @UseGuards(JWTGuard) @ApiBearerAuth('jwt-token') @Put('/nickname') - @ApiBody({ type: String }) + @ApiBody({ type: NicknameDto }) @ApiOperation({ - summary: '사용자 닉네임 변 경 API', + summary: '사용자 닉네임 변경 API', description: '사용자가 닉네임을 변경합니다' }) @ApiResponse({ status: 200, - type: String + description: '변경된 닉네임', + type: NicknameDto }) async updateNickname( @Req() req: any, @Body() nickname: string - ): Promise { + ): Promise { const result = this.userService.updateNickname(req.id, nickname); return result; } diff --git a/back/src/modules/user/user.service.ts b/back/src/modules/user/user.service.ts index 9e1a845..ebc1320 100644 --- a/back/src/modules/user/user.service.ts +++ b/back/src/modules/user/user.service.ts @@ -5,6 +5,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { ResInfoDto } from './dto/response/res-info.dto'; import { UserDto } from './dto/user.dto'; import { SnowballService } from '../snowball/snowball.service'; +import { NicknameDto } from './dto/nickname.dto'; @Injectable() export class UserService { @@ -74,7 +75,7 @@ export class UserService { return userDto; } - async updateNickname(id: number, nickname: string): Promise { + async updateNickname(id: number, nickname: string): Promise { const updateResult = await this.UserRepository.createQueryBuilder() .update(UserEntity) .set({ @@ -85,6 +86,6 @@ export class UserService { if (!updateResult.affected) { throw new NotFoundException('업데이트할 유저가 존재하지 않습니다.'); } - return 'test'; + return { nickname: nickname }; } } From e526b8343c09573ea5a4748b0d3642fe50614fa2 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Tue, 28 Nov 2023 13:23:53 +0900 Subject: [PATCH 118/185] =?UTF-8?q?fix:=20update=20nickname=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/user/user.service.ts | 13 ++++++++----- back/test/app.e2e-spec.ts | 24 ------------------------ back/test/jest-e2e.json | 9 --------- 3 files changed, 8 insertions(+), 38 deletions(-) delete mode 100644 back/test/app.e2e-spec.ts delete mode 100644 back/test/jest-e2e.json diff --git a/back/src/modules/user/user.service.ts b/back/src/modules/user/user.service.ts index ebc1320..134a26e 100644 --- a/back/src/modules/user/user.service.ts +++ b/back/src/modules/user/user.service.ts @@ -12,11 +12,11 @@ export class UserService { constructor( private readonly snowballService: SnowballService, @InjectRepository(UserEntity) - private readonly UserRepository: Repository + private readonly userRepository: Repository ) {} async getUserPk(user: any): Promise { - const exisitingUser = await this.UserRepository.findOne({ + const exisitingUser = await this.userRepository.findOne({ where: { user_id: user.id } }); if (exisitingUser) { @@ -27,9 +27,10 @@ export class UserService { } async getUserNickname(id: number): Promise { - const exisitingUser = await this.UserRepository.findOne({ + const exisitingUser = await this.userRepository.findOne({ where: { id: id } }); + console.log(exisitingUser); if (exisitingUser) { return exisitingUser.nickname; } else { @@ -62,6 +63,7 @@ export class UserService { const { snowball_count, message_count, snowball_list, main_snowball_id } = await this.snowballService.getSnowballInfo(id); const nickname = await this.getUserNickname(id); + console.log(nickname); const userDto: UserDto = { id: id, username: username, @@ -76,10 +78,11 @@ export class UserService { } async updateNickname(id: number, nickname: string): Promise { - const updateResult = await this.UserRepository.createQueryBuilder() + const updateResult = await this.userRepository + .createQueryBuilder() .update(UserEntity) .set({ - nickname: nickname + nickname: `${nickname}` }) .where('id = :id', { id: id }) .execute(); diff --git a/back/test/app.e2e-spec.ts b/back/test/app.e2e-spec.ts deleted file mode 100644 index 50cda62..0000000 --- a/back/test/app.e2e-spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { INestApplication } from '@nestjs/common'; -import * as request from 'supertest'; -import { AppModule } from './../src/app.module'; - -describe('AppController (e2e)', () => { - let app: INestApplication; - - beforeEach(async () => { - const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [AppModule], - }).compile(); - - app = moduleFixture.createNestApplication(); - await app.init(); - }); - - it('/ (GET)', () => { - return request(app.getHttpServer()) - .get('/') - .expect(200) - .expect('Hello World!'); - }); -}); diff --git a/back/test/jest-e2e.json b/back/test/jest-e2e.json deleted file mode 100644 index e9d912f..0000000 --- a/back/test/jest-e2e.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "moduleFileExtensions": ["js", "json", "ts"], - "rootDir": ".", - "testEnvironment": "node", - "testRegex": ".e2e-spec.ts$", - "transform": { - "^.+\\.(t|j)s$": "ts-jest" - } -} From 2e6f5c190efeaaf97270c13e48e7b51c28b66bc8 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Tue, 28 Nov 2023 13:34:32 +0900 Subject: [PATCH 119/185] =?UTF-8?q?fix:=20create=20snowball=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=8D=B0=EC=BD=94=20=EC=A7=80=EC=A0=95=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/req-create-snowball.dto.ts | 20 ++++++++++++------- back/src/modules/snowball/snowball.service.ts | 4 +++- back/src/modules/user/user.service.ts | 1 - 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts b/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts index 45cc886..512c6cd 100644 --- a/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts @@ -1,22 +1,28 @@ import { IsString, - IsNumber, IsNotEmpty, - IsBoolean + IsBoolean, + IsNumber, + IsHexColor } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class ReqCreateSnowballDto { - @IsNumber() - @IsNotEmpty() - @ApiProperty({ type: Number, description: '유저의 id' }) - readonly user_id: number; - @IsString() @IsNotEmpty() @ApiProperty({ type: String, description: '스노우볼 제목' }) readonly title: string; + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '장식 id' }) + readonly main_decoration_id: number; + + @IsHexColor() + @IsNotEmpty() + @ApiProperty({ type: String, description: '장식 색상', example: '#FFFFFF' }) + readonly main_decoration_color: string; + @IsBoolean() @IsNotEmpty() @ApiProperty({ diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 3bcfd05..200f562 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -32,7 +32,9 @@ export class SnowballService { const snowball = this.snowballRepository.create({ user_id: userid, title: createSnowballDto.title, - message_private: createSnowballDto.is_message_private ? new Date() : null + message_private: createSnowballDto.is_message_private ? new Date() : null, + main_decoration_color:createSnowballDto.main_decoration_color, + main_decoration_id:createSnowballDto.main_decoration_id }); const savedSnowball = await this.snowballRepository.save(snowball); diff --git a/back/src/modules/user/user.service.ts b/back/src/modules/user/user.service.ts index 134a26e..2afb4b3 100644 --- a/back/src/modules/user/user.service.ts +++ b/back/src/modules/user/user.service.ts @@ -30,7 +30,6 @@ export class UserService { const exisitingUser = await this.userRepository.findOne({ where: { id: id } }); - console.log(exisitingUser); if (exisitingUser) { return exisitingUser.nickname; } else { From ef1f85bf175f662449a5a326beae4e2363a14c78 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Tue, 28 Nov 2023 13:38:51 +0900 Subject: [PATCH 120/185] =?UTF-8?q?fix:=20=EC=8A=A4=EB=85=B8=EC=9A=B0?= =?UTF-8?q?=EB=B3=BC=20=EC=A1=B0=ED=9A=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/snowball/snowball.service.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 200f562..456ed15 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -32,9 +32,9 @@ export class SnowballService { const snowball = this.snowballRepository.create({ user_id: userid, title: createSnowballDto.title, - message_private: createSnowballDto.is_message_private ? new Date() : null, main_decoration_color:createSnowballDto.main_decoration_color, - main_decoration_id:createSnowballDto.main_decoration_id + main_decoration_id:createSnowballDto.main_decoration_id, + message_private: createSnowballDto.is_message_private ? new Date() : null }); const savedSnowball = await this.snowballRepository.save(snowball); @@ -104,8 +104,8 @@ export class SnowballService { letter_id: message.letter_id, location: message.location })), - main_decoration_id: 0, - main_decoration_color: '' + main_decoration_id: snowball.main_decoration_id, + main_decoration_color: snowball.main_decoration_color }; return resSnowball; From 45eb8a690f9bf4659ca7798b244c682a39b843e5 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Tue, 28 Nov 2023 13:43:14 +0900 Subject: [PATCH 121/185] =?UTF-8?q?fix:=20update=20snowball=20decoration?= =?UTF-8?q?=20Dto=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/snowball/dto/update-main-decoration.dto.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/back/src/modules/snowball/dto/update-main-decoration.dto.ts b/back/src/modules/snowball/dto/update-main-decoration.dto.ts index e5e173a..2882b6a 100644 --- a/back/src/modules/snowball/dto/update-main-decoration.dto.ts +++ b/back/src/modules/snowball/dto/update-main-decoration.dto.ts @@ -2,11 +2,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsNumber, IsNotEmpty, IsHexColor } from 'class-validator'; export class UpdateMainDecoDto { - @IsNumber() - @IsNotEmpty() - @ApiProperty({ type: Number, description: '스노우볼 id' }) - readonly snowball_id: number; - @IsNumber() @IsNotEmpty() @ApiProperty({ type: Number, description: '장식 id' }) From 07696f519573d98a092a21714e12b2ec5e36a3aa Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Tue, 28 Nov 2023 13:47:54 +0900 Subject: [PATCH 122/185] =?UTF-8?q?fix:=20create=20=EB=A9=94=EC=84=B8?= =?UTF-8?q?=EC=A7=80=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/message/dto/request/req-create-message.dto.ts | 6 ++++++ back/src/modules/message/message.service.ts | 1 + 2 files changed, 7 insertions(+) diff --git a/back/src/modules/message/dto/request/req-create-message.dto.ts b/back/src/modules/message/dto/request/req-create-message.dto.ts index f78c20f..bb5fdb7 100644 --- a/back/src/modules/message/dto/request/req-create-message.dto.ts +++ b/back/src/modules/message/dto/request/req-create-message.dto.ts @@ -22,6 +22,12 @@ export class ReqCreateMessageDto { @ApiProperty({ type: String, description: '장식 색상', example: '#FFFFFF' }) readonly decoration_color: string; + // To Do: location 프론트가 정할 지 우리가 정할 지 + @IsNumber() + @IsNotEmpty() + @ApiProperty({ type: Number, description: '장식 위치' }) + readonly location: number; + @IsNumber() @IsNotEmpty() @ApiProperty({ type: Number, description: '편지지 종류' }) diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 70ac9cc..7808b8f 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -33,6 +33,7 @@ export class MessageService { content: createMessageDto.content, decoration_id: createMessageDto.decoration_id, decoration_color: createMessageDto.decoration_color, + location: createMessageDto.location, letter_id: createMessageDto.letter_id, opened: null // is_deleted랑 created는 자동으로 설정 From d545fb8fc575790e44cb93abe86c02d11d9a0ae2 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Tue, 28 Nov 2023 13:54:04 +0900 Subject: [PATCH 123/185] =?UTF-8?q?fix:=20create=20=EB=A9=94=EC=84=B8?= =?UTF-8?q?=EC=A7=80=20plainToClass=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.service.ts | 27 ++------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 7808b8f..2bf44a8 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -14,6 +14,7 @@ import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; import { MessageDto } from './dto/message.dto'; import { ReqUpdateMessageDecorationDto } from './dto/request/req-update-message-decoration.dto'; import { ReqUpdateMessageLocationDto } from './dto/request/req-update-message-location.dto'; +import { plainToClass } from '@nestjs/class-transformer'; @Injectable() export class MessageService { @@ -81,31 +82,7 @@ export class MessageService { if (!messages) { throw new NotFoundException(`User with id ${user_id} not found`); } - const messagesDto: MessageDto[] = messages.map(message => { - const { - id, - decoration_id, - decoration_color, - letter_id, - content, - sender, - opened, - created, - location - } = message; - return { - id, - decoration_id, - decoration_color, - letter_id, - content, - sender, - opened, - created, - location - }; - }); - // const messagesDto: MessageDto[] = plainToClass(MessageDto, messages); + const messagesDto: MessageDto[] = plainToClass(MessageDto, messages); return messagesDto; } From 6c5bf7cb42627c0b1d701a3775a3282e6706a673 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Tue, 28 Nov 2023 14:03:48 +0900 Subject: [PATCH 124/185] =?UTF-8?q?fix:=20api=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EB=8F=99=EC=9E=91=20=EB=AA=A8=EB=91=90=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=20!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...to.ts => update-message-decoration.dto.ts} | 2 +- ....dto.ts => update-message-location.dto.ts} | 2 +- .../src/modules/message/message.controller.ts | 13 ++++++------- back/src/modules/message/message.service.ts | 19 +++++++++---------- 4 files changed, 17 insertions(+), 19 deletions(-) rename back/src/modules/message/dto/{request/req-update-message-decoration.dto.ts => update-message-decoration.dto.ts} (89%) rename back/src/modules/message/dto/{request/req-update-message-location.dto.ts => update-message-location.dto.ts} (84%) diff --git a/back/src/modules/message/dto/request/req-update-message-decoration.dto.ts b/back/src/modules/message/dto/update-message-decoration.dto.ts similarity index 89% rename from back/src/modules/message/dto/request/req-update-message-decoration.dto.ts rename to back/src/modules/message/dto/update-message-decoration.dto.ts index dc8d98d..dcbc708 100644 --- a/back/src/modules/message/dto/request/req-update-message-decoration.dto.ts +++ b/back/src/modules/message/dto/update-message-decoration.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsNumber, IsNotEmpty, IsHexColor } from 'class-validator'; -export class ReqUpdateMessageDecorationDto { +export class UpdateMessageDecorationDto { @IsNumber() @IsNotEmpty() @ApiProperty({ type: Number, description: '장식 id' }) diff --git a/back/src/modules/message/dto/request/req-update-message-location.dto.ts b/back/src/modules/message/dto/update-message-location.dto.ts similarity index 84% rename from back/src/modules/message/dto/request/req-update-message-location.dto.ts rename to back/src/modules/message/dto/update-message-location.dto.ts index 4a6d01e..e3db31c 100644 --- a/back/src/modules/message/dto/request/req-update-message-location.dto.ts +++ b/back/src/modules/message/dto/update-message-location.dto.ts @@ -1,7 +1,7 @@ import { IsNotEmpty, IsNumber } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -export class ReqUpdateMessageLocationDto { +export class UpdateMessageLocationDto { @IsNumber() @IsNotEmpty() @ApiProperty({ type: Number, description: '메시지 위치' }) diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 378a824..021fd5b 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -28,9 +28,8 @@ import { import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; import { MessageDto } from './dto/message.dto'; import { JWTGuard } from '../auth/auth.guard'; -import { ReqUpdateMessageDecorationDto } from './dto/request/req-update-message-decoration.dto'; -import { ReqUpdateMessageLocationDto } from './dto/request/req-update-message-location.dto'; - +import { UpdateMessageDecorationDto } from './dto/update-message-decoration.dto'; +import { UpdateMessageLocationDto } from './dto/update-message-location.dto'; @ApiTags('Message API') @Controller('message') export class MessageController { @@ -164,8 +163,8 @@ export class MessageController { }) async updateMessageDecoration( @Param('message_id') message_id: number, - @Body() updateMessageDecorationDto: ReqUpdateMessageDecorationDto - ): Promise { + @Body() updateMessageDecorationDto: UpdateMessageDecorationDto + ): Promise { return await this.messageService.updateMessageDecoration( message_id, updateMessageDecorationDto @@ -197,8 +196,8 @@ export class MessageController { }) async updateMessageLocation( @Param('message_id') message_id: number, - @Body() updateMessageLocationDto: ReqUpdateMessageLocationDto - ): Promise { + @Body() updateMessageLocationDto: UpdateMessageLocationDto + ): Promise { return await this.messageService.updateMessageLocation( message_id, updateMessageLocationDto diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 2bf44a8..04de1aa 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -12,9 +12,9 @@ import { ReqCreateMessageDto } from './dto/request/req-create-message.dto'; import { MessageEntity } from './entity/message.entity'; import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; import { MessageDto } from './dto/message.dto'; -import { ReqUpdateMessageDecorationDto } from './dto/request/req-update-message-decoration.dto'; -import { ReqUpdateMessageLocationDto } from './dto/request/req-update-message-location.dto'; import { plainToClass } from '@nestjs/class-transformer'; +import { UpdateMessageDecorationDto } from './dto/update-message-decoration.dto'; +import { UpdateMessageLocationDto } from './dto/update-message-location.dto'; @Injectable() export class MessageService { @@ -111,8 +111,8 @@ export class MessageService { async updateMessageDecoration( message_id: number, - updateMessageDecorationDto: ReqUpdateMessageDecorationDto - ): Promise { + updateMessageDecorationDto: UpdateMessageDecorationDto + ): Promise { const { decoration_id, decoration_color } = updateMessageDecorationDto; const updateResult = await this.messageRepository .createQueryBuilder() @@ -122,20 +122,20 @@ export class MessageService { decoration_color }) .where('id = :id', { id: message_id }) - .returning('*') .execute(); + console.log(updateResult); if (!updateResult.affected) { throw new NotFoundException('업데이트할 메시지가 존재하지 않습니다.'); } else if (updateResult.affected > 1) { throw new InternalServerErrorException('서버측 오류'); } - return updateResult.raw[0] as MessageDto; + return updateMessageDecorationDto; } async updateMessageLocation( message_id: number, - updateMessageLocationDto: ReqUpdateMessageLocationDto - ): Promise { + updateMessageLocationDto: UpdateMessageLocationDto + ): Promise { //TODO: location이 available 한지 확인 해야함 const { location } = updateMessageLocationDto; const updateResult = await this.messageRepository @@ -145,14 +145,13 @@ export class MessageService { location }) .where('id = :id', { id: message_id }) - .returning('*') .execute(); if (!updateResult.affected) { throw new NotFoundException('업데이트할 메시지가 존재하지 않습니다.'); } else if (updateResult.affected > 1) { throw new InternalServerErrorException('서버측 오류'); } - return updateResult.raw[0] as MessageDto; + return updateMessageLocationDto; } async getMessageCount(user_pk: number): Promise { From ce8204d3961986b68e169b9bb91b6d604b5fb14f Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Tue, 28 Nov 2023 14:53:03 +0900 Subject: [PATCH 125/185] =?UTF-8?q?fix:=20=EB=B0=A9=EB=AC=B8=EC=9E=90=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=20=EC=A1=B0=ED=9A=8C=20api=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/snowball/snowball.service.ts | 6 +++--- back/src/modules/user/user.controller.ts | 8 ++++---- back/src/modules/user/user.service.ts | 18 ++++++++++++------ 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 456ed15..90499ac 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -92,6 +92,8 @@ export class SnowballService { const resSnowball: SnowballDto = { id: snowball.id, title: snowball.title, + main_decoration_id: snowball.main_decoration_id, + main_decoration_color: snowball.main_decoration_color, is_message_private: snowball.message_private ? true : false, message_list: snowball.messages.map(message => ({ id: message.id, @@ -103,9 +105,7 @@ export class SnowballService { created: message.created, letter_id: message.letter_id, location: message.location - })), - main_decoration_id: snowball.main_decoration_id, - main_decoration_color: snowball.main_decoration_color + })) }; return resSnowball; diff --git a/back/src/modules/user/user.controller.ts b/back/src/modules/user/user.controller.ts index 18f7947..14219f6 100644 --- a/back/src/modules/user/user.controller.ts +++ b/back/src/modules/user/user.controller.ts @@ -53,8 +53,8 @@ export class UserController { async createVisitInfo( @Param('user_id') user_id: string ): Promise { - const user_pk = this.userService.getUserPk(user_id); - const result = this.userService.createUserInfo(user_pk); + const userData = await this.userService.getUserData(user_id); + const result = this.userService.createUserInfo(userData); return result; } @@ -73,9 +73,9 @@ export class UserController { }) async updateNickname( @Req() req: any, - @Body() nickname: string + @Body() nicknameDto: NicknameDto ): Promise { - const result = this.userService.updateNickname(req.id, nickname); + const result = this.userService.updateNickname(req.id, nicknameDto); return result; } } diff --git a/back/src/modules/user/user.service.ts b/back/src/modules/user/user.service.ts index 2afb4b3..5d64133 100644 --- a/back/src/modules/user/user.service.ts +++ b/back/src/modules/user/user.service.ts @@ -7,6 +7,12 @@ import { UserDto } from './dto/user.dto'; import { SnowballService } from '../snowball/snowball.service'; import { NicknameDto } from './dto/nickname.dto'; +interface userData { + id: number; + name: string; + user_id: string; +} + @Injectable() export class UserService { constructor( @@ -15,12 +21,12 @@ export class UserService { private readonly userRepository: Repository ) {} - async getUserPk(user: any): Promise { + async getUserData(user_id: string): Promise { const exisitingUser = await this.userRepository.findOne({ - where: { user_id: user.id } + where: { user_id: user_id } }); if (exisitingUser) { - return exisitingUser.id; + return {id:exisitingUser.id, name:exisitingUser.username, user_id:exisitingUser.user_id}; } else { throw new NotFoundException('해당 유저를 찾을 수 없습니다.'); } @@ -76,18 +82,18 @@ export class UserService { return userDto; } - async updateNickname(id: number, nickname: string): Promise { + async updateNickname(id: number, nicknameDto: NicknameDto): Promise { const updateResult = await this.userRepository .createQueryBuilder() .update(UserEntity) .set({ - nickname: `${nickname}` + nickname:nicknameDto.nickname }) .where('id = :id', { id: id }) .execute(); if (!updateResult.affected) { throw new NotFoundException('업데이트할 유저가 존재하지 않습니다.'); } - return { nickname: nickname }; + return nicknameDto; } } From 8c6fb7505a914f932208afcbcd715c60bcaedc61 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Tue, 28 Nov 2023 16:03:54 +0900 Subject: [PATCH 126/185] =?UTF-8?q?fix:=20access=20token=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5,=20todo=20=EB=A9=94=EB=AA=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.controller.ts | 26 +++++++++++-------- .../modules/message/entity/message.entity.ts | 2 ++ .../snowball/entity/snowball.entity.ts | 3 ++- back/src/modules/user/entity/user.entity.ts | 5 +++- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index 3efc0ac..d474f71 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -39,10 +39,11 @@ export class AuthController { }) async googleLoginCallback(@Req() req: any, @Res() res: any): Promise { const payload: payload = await this.authService.getUserInfo(req.user); - const { accessToken, refreshToken } = - this.authService.generateJwtToken(payload); - res.setHeader('Authorization', `Bearer ${accessToken}`); - // To DO: refresh token db에 저장 & 클라이언트에는 index만 저장? + const { accessToken, refreshToken } = this.authService.generateJwtToken(payload); + res.cookie('access_token', accessToken, { + httpOnly: true, + maxAge: parseInt(`${process.env.JWT_ACCESS_AGE}`) + }); res.cookie('refresh_token', refreshToken, { httpOnly: true, maxAge: parseInt(`${process.env.JWT_REFRESH_AGE}`) @@ -80,10 +81,11 @@ export class AuthController { }) async naverLoginCallBack(@Req() req: any, @Res() res: any): Promise { const payload: payload = await this.authService.getUserInfo(req.user); - const { accessToken, refreshToken } = - this.authService.generateJwtToken(payload); - res.setHeader('Authorization', `Bearer ${accessToken}`); - // To DO: refresh token db에 저장 & 클라이언트에는 index만 저장? + const { accessToken, refreshToken } = this.authService.generateJwtToken(payload); + res.cookie('access_token', accessToken, { + httpOnly: true, + maxAge: parseInt(`${process.env.JWT_ACCESS_AGE}`) + }); res.cookie('refresh_token', refreshToken, { httpOnly: true, maxAge: parseInt(`${process.env.JWT_REFRESH_AGE}`) @@ -121,10 +123,12 @@ export class AuthController { }) async kakaoLoginCallBack(@Req() req: any, @Res() res: any): Promise { const payload: payload = await this.authService.getUserInfo(req.user); - const { accessToken, refreshToken } = - this.authService.generateJwtToken(payload); - res.setHeader('Authorization', `Bearer ${accessToken}`); // To DO: refresh token db에 저장 & 클라이언트에는 index만 저장? + const { accessToken, refreshToken } = this.authService.generateJwtToken(payload); + res.cookie('access_token', accessToken, { + httpOnly: true, + maxAge: parseInt(`${process.env.JWT_ACCESS_AGE}`) + }); res.cookie('refresh_token', refreshToken, { httpOnly: true, maxAge: parseInt(`${process.env.JWT_REFRESH_AGE}`) diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 9d11991..acbf4f9 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -29,9 +29,11 @@ export class MessageEntity { @Column() letter_id: number; + // 500자 @Column({ type: 'text' }) content: string; + // 16자 @Column({ length: 16 }) sender: string; diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index 7117e93..c234560 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -18,7 +18,8 @@ export class SnowballEntity { @Column() user_id: number; - @Column({ length: 16 }) + // 10글자 + @Column({ length: 10 }) title: string; @CreateDateColumn() diff --git a/back/src/modules/user/entity/user.entity.ts b/back/src/modules/user/entity/user.entity.ts index 3790b08..610234c 100644 --- a/back/src/modules/user/entity/user.entity.ts +++ b/back/src/modules/user/entity/user.entity.ts @@ -18,13 +18,16 @@ export class UserEntity { @Column({ length: 45 }) user_id: string; + // kakao, naver, google에서 주는 거임 @Column({ length: 16 }) username: string; + // 닉네임?? 16자? @Column({ length: 16, default: null }) nickname: string | null; - @Column({ length: 16 }) + // kakao, naver, google + @Column({ length: 6 }) provider: string; @CreateDateColumn() From f713cf9e0a9b283edc8b6672791c9eb51d9aa131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 28 Nov 2023 21:51:14 +0900 Subject: [PATCH 127/185] =?UTF-8?q?feat:=20GET=20snowball=20join->select?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.controller.ts | 9 +++++--- .../modules/message/entity/message.entity.ts | 2 +- back/src/modules/message/message.service.ts | 9 +++++++- .../snowball/entity/snowball.entity.ts | 1 - back/src/modules/snowball/snowball.service.ts | 21 ++++--------------- 5 files changed, 19 insertions(+), 23 deletions(-) diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index d474f71..8f389d2 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -39,7 +39,8 @@ export class AuthController { }) async googleLoginCallback(@Req() req: any, @Res() res: any): Promise { const payload: payload = await this.authService.getUserInfo(req.user); - const { accessToken, refreshToken } = this.authService.generateJwtToken(payload); + const { accessToken, refreshToken } = + this.authService.generateJwtToken(payload); res.cookie('access_token', accessToken, { httpOnly: true, maxAge: parseInt(`${process.env.JWT_ACCESS_AGE}`) @@ -81,7 +82,8 @@ export class AuthController { }) async naverLoginCallBack(@Req() req: any, @Res() res: any): Promise { const payload: payload = await this.authService.getUserInfo(req.user); - const { accessToken, refreshToken } = this.authService.generateJwtToken(payload); + const { accessToken, refreshToken } = + this.authService.generateJwtToken(payload); res.cookie('access_token', accessToken, { httpOnly: true, maxAge: parseInt(`${process.env.JWT_ACCESS_AGE}`) @@ -124,7 +126,8 @@ export class AuthController { async kakaoLoginCallBack(@Req() req: any, @Res() res: any): Promise { const payload: payload = await this.authService.getUserInfo(req.user); // To DO: refresh token db에 저장 & 클라이언트에는 index만 저장? - const { accessToken, refreshToken } = this.authService.generateJwtToken(payload); + const { accessToken, refreshToken } = + this.authService.generateJwtToken(payload); res.cookie('access_token', accessToken, { httpOnly: true, maxAge: parseInt(`${process.env.JWT_ACCESS_AGE}`) diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index acbf4f9..517d150 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -29,7 +29,7 @@ export class MessageEntity { @Column() letter_id: number; - // 500자 + // 500자 @Column({ type: 'text' }) content: string; diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 04de1aa..ed05cb7 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -123,7 +123,7 @@ export class MessageService { }) .where('id = :id', { id: message_id }) .execute(); - console.log(updateResult); + console.log(updateResult); if (!updateResult.affected) { throw new NotFoundException('업데이트할 메시지가 존재하지 않습니다.'); } else if (updateResult.affected > 1) { @@ -157,4 +157,11 @@ export class MessageService { async getMessageCount(user_pk: number): Promise { return this.messageRepository.count({ where: { user: { id: user_pk } } }); } + + async getMessageList(snowball_id: number): Promise { + const messages = await this.messageRepository.find({ + where: { snowball_id: snowball_id } + }); + return messages; + } } diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index c234560..6809132 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -18,7 +18,6 @@ export class SnowballEntity { @Column() user_id: number; - // 10글자 @Column({ length: 10 }) title: string; diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 90499ac..f311208 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -32,8 +32,8 @@ export class SnowballService { const snowball = this.snowballRepository.create({ user_id: userid, title: createSnowballDto.title, - main_decoration_color:createSnowballDto.main_decoration_color, - main_decoration_id:createSnowballDto.main_decoration_id, + main_decoration_color: createSnowballDto.main_decoration_color, + main_decoration_id: createSnowballDto.main_decoration_id, message_private: createSnowballDto.is_message_private ? new Date() : null }); const savedSnowball = await this.snowballRepository.save(snowball); @@ -80,10 +80,7 @@ export class SnowballService { async getSnowball(snowball_id: number): Promise | null { const snowball = await this.snowballRepository.findOne({ - where: { id: snowball_id }, - relations: { - messages: true - } + where: { id: snowball_id } }); if (!snowball) { return null; @@ -95,17 +92,7 @@ export class SnowballService { main_decoration_id: snowball.main_decoration_id, main_decoration_color: snowball.main_decoration_color, is_message_private: snowball.message_private ? true : false, - message_list: snowball.messages.map(message => ({ - id: message.id, - decoration_id: message.decoration_id, - decoration_color: message.decoration_color, - content: message.content, - sender: message.sender, - opened: message.opened, - created: message.created, - letter_id: message.letter_id, - location: message.location - })) + message_list: await this.messageService.getMessageList(snowball.id) }; return resSnowball; From 048deaeab48476ec3cf60a7769aac7d0cd4953c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 28 Nov 2023 22:39:15 +0900 Subject: [PATCH 128/185] =?UTF-8?q?feat:=20global=20Pipe=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20=EB=B0=8F=20=EB=A9=94=EC=84=B8=EC=A7=80=20validate?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/package-lock.json | 11 ++++++++ back/package.json | 1 + back/src/main.ts | 7 +++++ back/src/modules/message/dto/message.dto.ts | 25 +++++++++++++---- .../dto/request/req-create-message.dto.ts | 27 ++++++++++++++----- .../dto/response/res-create-message.dto.ts | 4 ++- .../dto/update-message-decoration.dto.ts | 3 ++- .../dto/update-message-location.dto.ts | 4 ++- .../modules/message/entity/message.entity.ts | 10 +++---- 9 files changed, 72 insertions(+), 20 deletions(-) diff --git a/back/package-lock.json b/back/package-lock.json index 2f5aee5..39b08a5 100644 --- a/back/package-lock.json +++ b/back/package-lock.json @@ -19,6 +19,7 @@ "@nestjs/platform-express": "^10.0.0", "@nestjs/swagger": "^7.1.16", "@nestjs/typeorm": "^10.0.0", + "class-transformer": "^0.5.1", "class-validator": "^0.14.0", "dotenv": "^16.3.1", "express-basic-auth": "^1.2.1", @@ -3736,6 +3737,11 @@ "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, + "node_modules/class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" + }, "node_modules/class-validator": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz", @@ -13626,6 +13632,11 @@ "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, + "class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" + }, "class-validator": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz", diff --git a/back/package.json b/back/package.json index f9f4693..f4969b5 100644 --- a/back/package.json +++ b/back/package.json @@ -30,6 +30,7 @@ "@nestjs/platform-express": "^10.0.0", "@nestjs/swagger": "^7.1.16", "@nestjs/typeorm": "^10.0.0", + "class-transformer": "^0.5.1", "class-validator": "^0.14.0", "dotenv": "^16.3.1", "express-basic-auth": "^1.2.1", diff --git a/back/src/main.ts b/back/src/main.ts index 5eebd09..a8957bc 100644 --- a/back/src/main.ts +++ b/back/src/main.ts @@ -1,10 +1,17 @@ import { NestFactory } from '@nestjs/core'; import { setupSwagger } from 'src/util/swagger'; import { AppModule } from './app.module'; +import { ValidationPipe } from '@nestjs/common/pipes'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.setGlobalPrefix('api'); + app.useGlobalPipes( + new ValidationPipe({ + forbidNonWhitelisted: true, + forbidUnknownValues: true + }) + ); setupSwagger(app); await app.listen(3000); } diff --git a/back/src/modules/message/dto/message.dto.ts b/back/src/modules/message/dto/message.dto.ts index cd41628..7a240ac 100644 --- a/back/src/modules/message/dto/message.dto.ts +++ b/back/src/modules/message/dto/message.dto.ts @@ -1,5 +1,13 @@ +import { Length } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -import { IsString, IsNumber, IsDate } from 'class-validator'; +import { + IsString, + IsNumber, + IsDate, + IsHexColor, + Min, + Max +} from 'class-validator'; export class MessageDto { @IsNumber() @@ -7,22 +15,27 @@ export class MessageDto { readonly id: number; @IsNumber() - @ApiProperty({ type: Number, description: '데코레이션 ID' }) + @Min(1) + @ApiProperty({ type: Number, description: '장식 id' }) readonly decoration_id: number; - @IsString() - @ApiProperty({ type: String, description: '데코레이션 색상' }) + @IsHexColor() + @ApiProperty({ type: String, description: '장식 색상' }) readonly decoration_color: string; @IsNumber() + @Min(1) + @Max(3) @ApiProperty({ type: Number, description: '편지지 종류' }) readonly letter_id: number; @IsString() + @Length(1, 500) @ApiProperty({ type: String, description: '메시지 내용' }) readonly content: string; @IsString() + @Length(1, 16) @ApiProperty({ type: String, description: '보낸이' }) readonly sender: string; @@ -35,6 +48,8 @@ export class MessageDto { readonly created: Date; @IsNumber() - @ApiProperty({ type: Number, description: '위치값' }) + @Min(1) + @Max(72) + @ApiProperty({ type: Number, description: '메세지 위치' }) readonly location: number; } diff --git a/back/src/modules/message/dto/request/req-create-message.dto.ts b/back/src/modules/message/dto/request/req-create-message.dto.ts index bb5fdb7..2eb20db 100644 --- a/back/src/modules/message/dto/request/req-create-message.dto.ts +++ b/back/src/modules/message/dto/request/req-create-message.dto.ts @@ -1,35 +1,50 @@ -import { IsString, IsNotEmpty, IsNumber } from '@nestjs/class-validator'; +import { + IsString, + IsNotEmpty, + IsNumber, + IsHexColor, + Length, + Min, + Max +} from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class ReqCreateMessageDto { @IsString() + @Length(1, 16) @IsNotEmpty() @ApiProperty({ type: String, description: '익명 사용자 닉네임(From)' }) readonly sender: string; @IsString() + @Length(1, 500) @IsNotEmpty() @ApiProperty({ type: String, description: '메세지 내용' }) readonly content: string; + // To Do: decoration_prefix 테이블 사용 @IsNumber() + @Min(1) @IsNotEmpty() - @ApiProperty({ type: Number, description: '장식 종류' }) + @ApiProperty({ type: Number, description: '장식 id', example: 1 }) readonly decoration_id: number; - @IsString() + @IsHexColor() @IsNotEmpty() @ApiProperty({ type: String, description: '장식 색상', example: '#FFFFFF' }) readonly decoration_color: string; - // To Do: location 프론트가 정할 지 우리가 정할 지 @IsNumber() + @Min(1) + @Max(72) @IsNotEmpty() - @ApiProperty({ type: Number, description: '장식 위치' }) + @ApiProperty({ type: Number, description: '장식 위치', example: 1 }) readonly location: number; @IsNumber() + @Min(1) + @Max(3) @IsNotEmpty() - @ApiProperty({ type: Number, description: '편지지 종류' }) + @ApiProperty({ type: Number, description: '편지지 종류', example: 1 }) readonly letter_id: number; } diff --git a/back/src/modules/message/dto/response/res-create-message.dto.ts b/back/src/modules/message/dto/response/res-create-message.dto.ts index 4e3931c..e8b7cd9 100644 --- a/back/src/modules/message/dto/response/res-create-message.dto.ts +++ b/back/src/modules/message/dto/response/res-create-message.dto.ts @@ -1,8 +1,9 @@ -import { IsString, IsNotEmpty } from '@nestjs/class-validator'; +import { IsString, IsNotEmpty, Length } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class ResCreateMessageDto { @IsString() + @Length(1, 16) @IsNotEmpty() @ApiProperty({ type: String, @@ -11,6 +12,7 @@ export class ResCreateMessageDto { readonly sender: string; @IsString() + @Length(1, 500) @IsNotEmpty() @ApiProperty({ type: String, description: '필터링된 메세지 내용' }) readonly content: string; diff --git a/back/src/modules/message/dto/update-message-decoration.dto.ts b/back/src/modules/message/dto/update-message-decoration.dto.ts index dcbc708..216a002 100644 --- a/back/src/modules/message/dto/update-message-decoration.dto.ts +++ b/back/src/modules/message/dto/update-message-decoration.dto.ts @@ -1,8 +1,9 @@ import { ApiProperty } from '@nestjs/swagger'; -import { IsNumber, IsNotEmpty, IsHexColor } from 'class-validator'; +import { IsNumber, IsNotEmpty, IsHexColor, Min } from 'class-validator'; export class UpdateMessageDecorationDto { @IsNumber() + @Min(1) @IsNotEmpty() @ApiProperty({ type: Number, description: '장식 id' }) readonly decoration_id: number; diff --git a/back/src/modules/message/dto/update-message-location.dto.ts b/back/src/modules/message/dto/update-message-location.dto.ts index e3db31c..67545ec 100644 --- a/back/src/modules/message/dto/update-message-location.dto.ts +++ b/back/src/modules/message/dto/update-message-location.dto.ts @@ -1,8 +1,10 @@ -import { IsNotEmpty, IsNumber } from '@nestjs/class-validator'; +import { IsNotEmpty, IsNumber, Min, Max } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class UpdateMessageLocationDto { @IsNumber() + @Min(1) + @Max(72) @IsNotEmpty() @ApiProperty({ type: Number, description: '메시지 위치' }) readonly location: number; diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 517d150..b9a3f9f 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -29,21 +29,19 @@ export class MessageEntity { @Column() letter_id: number; - // 500자 - @Column({ type: 'text' }) + @Column({ length: 500 }) content: string; - // 16자 @Column({ length: 16 }) sender: string; - @Column({ type: 'boolean', default: false }) + @Column({ default: false }) is_deleted: boolean; - @Column({ nullable: false }) + @Column() location: number; - @CreateDateColumn({ nullable: true, default: null }) + @CreateDateColumn({ default: null }) opened: Date | null; @CreateDateColumn() From 19f3d55a80f3bacea63b62df1dd8ec6b3a9f78af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 28 Nov 2023 22:44:34 +0900 Subject: [PATCH 129/185] =?UTF-8?q?feat:=20user=20validate=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=20=EB=B0=8F=20soft=20delete=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.service.ts | 2 +- back/src/modules/user/dto/nickname.dto.ts | 3 ++- back/src/modules/user/dto/user.dto.ts | 18 +++++++++++++++++- back/src/modules/user/entity/user.entity.ts | 3 --- back/src/modules/user/user.service.ts | 13 ++++++++++--- 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index ed05cb7..8766e09 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -160,7 +160,7 @@ export class MessageService { async getMessageList(snowball_id: number): Promise { const messages = await this.messageRepository.find({ - where: { snowball_id: snowball_id } + where: { snowball_id: snowball_id, is_deleted: false } }); return messages; } diff --git a/back/src/modules/user/dto/nickname.dto.ts b/back/src/modules/user/dto/nickname.dto.ts index 7f643f8..dc69360 100644 --- a/back/src/modules/user/dto/nickname.dto.ts +++ b/back/src/modules/user/dto/nickname.dto.ts @@ -1,8 +1,9 @@ -import { IsString } from '@nestjs/class-validator'; +import { IsString, Length } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class NicknameDto { @IsString() + @Length(1, 16) @ApiProperty({ type: String, description: '사용자 닉네임' }) readonly nickname: string | null; } diff --git a/back/src/modules/user/dto/user.dto.ts b/back/src/modules/user/dto/user.dto.ts index d3a7871..d206c95 100644 --- a/back/src/modules/user/dto/user.dto.ts +++ b/back/src/modules/user/dto/user.dto.ts @@ -1,4 +1,12 @@ -import { IsString, IsNumber, IsNotEmpty } from '@nestjs/class-validator'; +import { + IsString, + IsNumber, + IsNotEmpty, + Length, + Min, + Max, + IsPositive +} from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class UserDto { @@ -8,25 +16,31 @@ export class UserDto { readonly id: number; @IsString() + @Length(1, 16) @IsNotEmpty() @ApiProperty({ type: String, description: '사용자 이름' }) readonly username: string; @IsString() + @Length(1, 16) @ApiProperty({ type: String, description: '사용자 닉네임' }) readonly nickname: string | null; @IsString() + @Length(1, 45) @IsNotEmpty() @ApiProperty({ type: String, description: 'Oauth에서 주는 값' }) readonly user_id: string; @IsNumber() + @IsPositive() + @Max(5) @IsNotEmpty() @ApiProperty({ type: Number, description: '스노우볼 갯수' }) readonly snowball_count: number; @IsNumber() + @Min(1) @ApiProperty({ type: Number, description: '메인 스노우볼 id' }) readonly main_snowball_id: number | null; @@ -38,6 +52,8 @@ export class UserDto { readonly snowball_list: number[]; @IsNumber() + @IsPositive() + @Max(150) @IsNotEmpty() @ApiProperty({ type: Number, description: '메시지 갯수' }) readonly message_count: number; diff --git a/back/src/modules/user/entity/user.entity.ts b/back/src/modules/user/entity/user.entity.ts index 610234c..56eac28 100644 --- a/back/src/modules/user/entity/user.entity.ts +++ b/back/src/modules/user/entity/user.entity.ts @@ -18,15 +18,12 @@ export class UserEntity { @Column({ length: 45 }) user_id: string; - // kakao, naver, google에서 주는 거임 @Column({ length: 16 }) username: string; - // 닉네임?? 16자? @Column({ length: 16, default: null }) nickname: string | null; - // kakao, naver, google @Column({ length: 6 }) provider: string; diff --git a/back/src/modules/user/user.service.ts b/back/src/modules/user/user.service.ts index 5d64133..d3aaf49 100644 --- a/back/src/modules/user/user.service.ts +++ b/back/src/modules/user/user.service.ts @@ -26,7 +26,11 @@ export class UserService { where: { user_id: user_id } }); if (exisitingUser) { - return {id:exisitingUser.id, name:exisitingUser.username, user_id:exisitingUser.user_id}; + return { + id: exisitingUser.id, + name: exisitingUser.username, + user_id: exisitingUser.user_id + }; } else { throw new NotFoundException('해당 유저를 찾을 수 없습니다.'); } @@ -82,12 +86,15 @@ export class UserService { return userDto; } - async updateNickname(id: number, nicknameDto: NicknameDto): Promise { + async updateNickname( + id: number, + nicknameDto: NicknameDto + ): Promise { const updateResult = await this.userRepository .createQueryBuilder() .update(UserEntity) .set({ - nickname:nicknameDto.nickname + nickname: nicknameDto.nickname }) .where('id = :id', { id: id }) .execute(); From 09273e16f14e0dfc85a0f17933b33cfda6d2f190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 29 Nov 2023 10:49:21 +0900 Subject: [PATCH 130/185] =?UTF-8?q?feat:=20=EB=A9=94=EC=84=B8=EC=A7=80=20?= =?UTF-8?q?=EA=B0=9C=EC=88=98=20=EC=B4=88=EA=B3=BC=20conflict=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.service.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 8766e09..80e1c32 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -27,6 +27,8 @@ export class MessageService { user_id: number, snowball_id: number ): Promise { + if (!(await this.isInsertAllowed(snowball_id))) + throw new ConflictException('메세지 갯수가 30개를 초과했습니다'); const messageEntity = this.messageRepository.create({ user_id: user_id, snowball_id: snowball_id, @@ -49,6 +51,15 @@ export class MessageService { return resCreateMessage; } + + async isInsertAllowed(snowball_id: number): Promise { + const messageCount = await this.messageRepository.count({ + where: { snowball_id: snowball_id, is_deleted: false } + }); + if (messageCount >= 30) return false; + else return true; + } + async deleteMessage(user_id: number, message_id: number): Promise { try { const message = await this.messageRepository.findOne({ @@ -155,7 +166,9 @@ export class MessageService { } async getMessageCount(user_pk: number): Promise { - return this.messageRepository.count({ where: { user: { id: user_pk } } }); + return this.messageRepository.count({ + where: { user_id: user_pk, is_deleted: false } + }); } async getMessageList(snowball_id: number): Promise { From d2dd798fc32a838854b727509a111f21675eacc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 28 Nov 2023 21:51:14 +0900 Subject: [PATCH 131/185] =?UTF-8?q?feat:=20GET=20snowball=20join->select?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.controller.ts | 9 +++++--- .../modules/message/entity/message.entity.ts | 2 +- back/src/modules/message/message.service.ts | 9 +++++++- .../snowball/entity/snowball.entity.ts | 1 - back/src/modules/snowball/snowball.service.ts | 21 ++++--------------- 5 files changed, 19 insertions(+), 23 deletions(-) diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index d474f71..8f389d2 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -39,7 +39,8 @@ export class AuthController { }) async googleLoginCallback(@Req() req: any, @Res() res: any): Promise { const payload: payload = await this.authService.getUserInfo(req.user); - const { accessToken, refreshToken } = this.authService.generateJwtToken(payload); + const { accessToken, refreshToken } = + this.authService.generateJwtToken(payload); res.cookie('access_token', accessToken, { httpOnly: true, maxAge: parseInt(`${process.env.JWT_ACCESS_AGE}`) @@ -81,7 +82,8 @@ export class AuthController { }) async naverLoginCallBack(@Req() req: any, @Res() res: any): Promise { const payload: payload = await this.authService.getUserInfo(req.user); - const { accessToken, refreshToken } = this.authService.generateJwtToken(payload); + const { accessToken, refreshToken } = + this.authService.generateJwtToken(payload); res.cookie('access_token', accessToken, { httpOnly: true, maxAge: parseInt(`${process.env.JWT_ACCESS_AGE}`) @@ -124,7 +126,8 @@ export class AuthController { async kakaoLoginCallBack(@Req() req: any, @Res() res: any): Promise { const payload: payload = await this.authService.getUserInfo(req.user); // To DO: refresh token db에 저장 & 클라이언트에는 index만 저장? - const { accessToken, refreshToken } = this.authService.generateJwtToken(payload); + const { accessToken, refreshToken } = + this.authService.generateJwtToken(payload); res.cookie('access_token', accessToken, { httpOnly: true, maxAge: parseInt(`${process.env.JWT_ACCESS_AGE}`) diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index acbf4f9..517d150 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -29,7 +29,7 @@ export class MessageEntity { @Column() letter_id: number; - // 500자 + // 500자 @Column({ type: 'text' }) content: string; diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 04de1aa..ed05cb7 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -123,7 +123,7 @@ export class MessageService { }) .where('id = :id', { id: message_id }) .execute(); - console.log(updateResult); + console.log(updateResult); if (!updateResult.affected) { throw new NotFoundException('업데이트할 메시지가 존재하지 않습니다.'); } else if (updateResult.affected > 1) { @@ -157,4 +157,11 @@ export class MessageService { async getMessageCount(user_pk: number): Promise { return this.messageRepository.count({ where: { user: { id: user_pk } } }); } + + async getMessageList(snowball_id: number): Promise { + const messages = await this.messageRepository.find({ + where: { snowball_id: snowball_id } + }); + return messages; + } } diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index c234560..6809132 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -18,7 +18,6 @@ export class SnowballEntity { @Column() user_id: number; - // 10글자 @Column({ length: 10 }) title: string; diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 90499ac..f311208 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -32,8 +32,8 @@ export class SnowballService { const snowball = this.snowballRepository.create({ user_id: userid, title: createSnowballDto.title, - main_decoration_color:createSnowballDto.main_decoration_color, - main_decoration_id:createSnowballDto.main_decoration_id, + main_decoration_color: createSnowballDto.main_decoration_color, + main_decoration_id: createSnowballDto.main_decoration_id, message_private: createSnowballDto.is_message_private ? new Date() : null }); const savedSnowball = await this.snowballRepository.save(snowball); @@ -80,10 +80,7 @@ export class SnowballService { async getSnowball(snowball_id: number): Promise | null { const snowball = await this.snowballRepository.findOne({ - where: { id: snowball_id }, - relations: { - messages: true - } + where: { id: snowball_id } }); if (!snowball) { return null; @@ -95,17 +92,7 @@ export class SnowballService { main_decoration_id: snowball.main_decoration_id, main_decoration_color: snowball.main_decoration_color, is_message_private: snowball.message_private ? true : false, - message_list: snowball.messages.map(message => ({ - id: message.id, - decoration_id: message.decoration_id, - decoration_color: message.decoration_color, - content: message.content, - sender: message.sender, - opened: message.opened, - created: message.created, - letter_id: message.letter_id, - location: message.location - })) + message_list: await this.messageService.getMessageList(snowball.id) }; return resSnowball; From 5529b27930bc9f0c3797e7025d1eebda8540ee1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 28 Nov 2023 22:39:15 +0900 Subject: [PATCH 132/185] =?UTF-8?q?feat:=20global=20Pipe=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20=EB=B0=8F=20=EB=A9=94=EC=84=B8=EC=A7=80=20validate?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/package-lock.json | 11 ++++++++ back/package.json | 1 + back/src/main.ts | 7 +++++ back/src/modules/message/dto/message.dto.ts | 25 +++++++++++++---- .../dto/request/req-create-message.dto.ts | 27 ++++++++++++++----- .../dto/response/res-create-message.dto.ts | 4 ++- .../dto/update-message-decoration.dto.ts | 3 ++- .../dto/update-message-location.dto.ts | 4 ++- .../modules/message/entity/message.entity.ts | 10 +++---- 9 files changed, 72 insertions(+), 20 deletions(-) diff --git a/back/package-lock.json b/back/package-lock.json index 2f5aee5..39b08a5 100644 --- a/back/package-lock.json +++ b/back/package-lock.json @@ -19,6 +19,7 @@ "@nestjs/platform-express": "^10.0.0", "@nestjs/swagger": "^7.1.16", "@nestjs/typeorm": "^10.0.0", + "class-transformer": "^0.5.1", "class-validator": "^0.14.0", "dotenv": "^16.3.1", "express-basic-auth": "^1.2.1", @@ -3736,6 +3737,11 @@ "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, + "node_modules/class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" + }, "node_modules/class-validator": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz", @@ -13626,6 +13632,11 @@ "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, + "class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" + }, "class-validator": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz", diff --git a/back/package.json b/back/package.json index f9f4693..f4969b5 100644 --- a/back/package.json +++ b/back/package.json @@ -30,6 +30,7 @@ "@nestjs/platform-express": "^10.0.0", "@nestjs/swagger": "^7.1.16", "@nestjs/typeorm": "^10.0.0", + "class-transformer": "^0.5.1", "class-validator": "^0.14.0", "dotenv": "^16.3.1", "express-basic-auth": "^1.2.1", diff --git a/back/src/main.ts b/back/src/main.ts index 5eebd09..a8957bc 100644 --- a/back/src/main.ts +++ b/back/src/main.ts @@ -1,10 +1,17 @@ import { NestFactory } from '@nestjs/core'; import { setupSwagger } from 'src/util/swagger'; import { AppModule } from './app.module'; +import { ValidationPipe } from '@nestjs/common/pipes'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.setGlobalPrefix('api'); + app.useGlobalPipes( + new ValidationPipe({ + forbidNonWhitelisted: true, + forbidUnknownValues: true + }) + ); setupSwagger(app); await app.listen(3000); } diff --git a/back/src/modules/message/dto/message.dto.ts b/back/src/modules/message/dto/message.dto.ts index cd41628..7a240ac 100644 --- a/back/src/modules/message/dto/message.dto.ts +++ b/back/src/modules/message/dto/message.dto.ts @@ -1,5 +1,13 @@ +import { Length } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; -import { IsString, IsNumber, IsDate } from 'class-validator'; +import { + IsString, + IsNumber, + IsDate, + IsHexColor, + Min, + Max +} from 'class-validator'; export class MessageDto { @IsNumber() @@ -7,22 +15,27 @@ export class MessageDto { readonly id: number; @IsNumber() - @ApiProperty({ type: Number, description: '데코레이션 ID' }) + @Min(1) + @ApiProperty({ type: Number, description: '장식 id' }) readonly decoration_id: number; - @IsString() - @ApiProperty({ type: String, description: '데코레이션 색상' }) + @IsHexColor() + @ApiProperty({ type: String, description: '장식 색상' }) readonly decoration_color: string; @IsNumber() + @Min(1) + @Max(3) @ApiProperty({ type: Number, description: '편지지 종류' }) readonly letter_id: number; @IsString() + @Length(1, 500) @ApiProperty({ type: String, description: '메시지 내용' }) readonly content: string; @IsString() + @Length(1, 16) @ApiProperty({ type: String, description: '보낸이' }) readonly sender: string; @@ -35,6 +48,8 @@ export class MessageDto { readonly created: Date; @IsNumber() - @ApiProperty({ type: Number, description: '위치값' }) + @Min(1) + @Max(72) + @ApiProperty({ type: Number, description: '메세지 위치' }) readonly location: number; } diff --git a/back/src/modules/message/dto/request/req-create-message.dto.ts b/back/src/modules/message/dto/request/req-create-message.dto.ts index bb5fdb7..2eb20db 100644 --- a/back/src/modules/message/dto/request/req-create-message.dto.ts +++ b/back/src/modules/message/dto/request/req-create-message.dto.ts @@ -1,35 +1,50 @@ -import { IsString, IsNotEmpty, IsNumber } from '@nestjs/class-validator'; +import { + IsString, + IsNotEmpty, + IsNumber, + IsHexColor, + Length, + Min, + Max +} from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class ReqCreateMessageDto { @IsString() + @Length(1, 16) @IsNotEmpty() @ApiProperty({ type: String, description: '익명 사용자 닉네임(From)' }) readonly sender: string; @IsString() + @Length(1, 500) @IsNotEmpty() @ApiProperty({ type: String, description: '메세지 내용' }) readonly content: string; + // To Do: decoration_prefix 테이블 사용 @IsNumber() + @Min(1) @IsNotEmpty() - @ApiProperty({ type: Number, description: '장식 종류' }) + @ApiProperty({ type: Number, description: '장식 id', example: 1 }) readonly decoration_id: number; - @IsString() + @IsHexColor() @IsNotEmpty() @ApiProperty({ type: String, description: '장식 색상', example: '#FFFFFF' }) readonly decoration_color: string; - // To Do: location 프론트가 정할 지 우리가 정할 지 @IsNumber() + @Min(1) + @Max(72) @IsNotEmpty() - @ApiProperty({ type: Number, description: '장식 위치' }) + @ApiProperty({ type: Number, description: '장식 위치', example: 1 }) readonly location: number; @IsNumber() + @Min(1) + @Max(3) @IsNotEmpty() - @ApiProperty({ type: Number, description: '편지지 종류' }) + @ApiProperty({ type: Number, description: '편지지 종류', example: 1 }) readonly letter_id: number; } diff --git a/back/src/modules/message/dto/response/res-create-message.dto.ts b/back/src/modules/message/dto/response/res-create-message.dto.ts index 4e3931c..e8b7cd9 100644 --- a/back/src/modules/message/dto/response/res-create-message.dto.ts +++ b/back/src/modules/message/dto/response/res-create-message.dto.ts @@ -1,8 +1,9 @@ -import { IsString, IsNotEmpty } from '@nestjs/class-validator'; +import { IsString, IsNotEmpty, Length } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class ResCreateMessageDto { @IsString() + @Length(1, 16) @IsNotEmpty() @ApiProperty({ type: String, @@ -11,6 +12,7 @@ export class ResCreateMessageDto { readonly sender: string; @IsString() + @Length(1, 500) @IsNotEmpty() @ApiProperty({ type: String, description: '필터링된 메세지 내용' }) readonly content: string; diff --git a/back/src/modules/message/dto/update-message-decoration.dto.ts b/back/src/modules/message/dto/update-message-decoration.dto.ts index dcbc708..216a002 100644 --- a/back/src/modules/message/dto/update-message-decoration.dto.ts +++ b/back/src/modules/message/dto/update-message-decoration.dto.ts @@ -1,8 +1,9 @@ import { ApiProperty } from '@nestjs/swagger'; -import { IsNumber, IsNotEmpty, IsHexColor } from 'class-validator'; +import { IsNumber, IsNotEmpty, IsHexColor, Min } from 'class-validator'; export class UpdateMessageDecorationDto { @IsNumber() + @Min(1) @IsNotEmpty() @ApiProperty({ type: Number, description: '장식 id' }) readonly decoration_id: number; diff --git a/back/src/modules/message/dto/update-message-location.dto.ts b/back/src/modules/message/dto/update-message-location.dto.ts index e3db31c..67545ec 100644 --- a/back/src/modules/message/dto/update-message-location.dto.ts +++ b/back/src/modules/message/dto/update-message-location.dto.ts @@ -1,8 +1,10 @@ -import { IsNotEmpty, IsNumber } from '@nestjs/class-validator'; +import { IsNotEmpty, IsNumber, Min, Max } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class UpdateMessageLocationDto { @IsNumber() + @Min(1) + @Max(72) @IsNotEmpty() @ApiProperty({ type: Number, description: '메시지 위치' }) readonly location: number; diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index 517d150..b9a3f9f 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -29,21 +29,19 @@ export class MessageEntity { @Column() letter_id: number; - // 500자 - @Column({ type: 'text' }) + @Column({ length: 500 }) content: string; - // 16자 @Column({ length: 16 }) sender: string; - @Column({ type: 'boolean', default: false }) + @Column({ default: false }) is_deleted: boolean; - @Column({ nullable: false }) + @Column() location: number; - @CreateDateColumn({ nullable: true, default: null }) + @CreateDateColumn({ default: null }) opened: Date | null; @CreateDateColumn() From 2b472e901dea38241ff1add12a708004392a05a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Tue, 28 Nov 2023 22:44:34 +0900 Subject: [PATCH 133/185] =?UTF-8?q?feat:=20user=20validate=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=20=EB=B0=8F=20soft=20delete=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.service.ts | 2 +- back/src/modules/user/dto/nickname.dto.ts | 3 ++- back/src/modules/user/dto/user.dto.ts | 18 +++++++++++++++++- back/src/modules/user/entity/user.entity.ts | 3 --- back/src/modules/user/user.service.ts | 13 ++++++++++--- 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index ed05cb7..8766e09 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -160,7 +160,7 @@ export class MessageService { async getMessageList(snowball_id: number): Promise { const messages = await this.messageRepository.find({ - where: { snowball_id: snowball_id } + where: { snowball_id: snowball_id, is_deleted: false } }); return messages; } diff --git a/back/src/modules/user/dto/nickname.dto.ts b/back/src/modules/user/dto/nickname.dto.ts index 7f643f8..dc69360 100644 --- a/back/src/modules/user/dto/nickname.dto.ts +++ b/back/src/modules/user/dto/nickname.dto.ts @@ -1,8 +1,9 @@ -import { IsString } from '@nestjs/class-validator'; +import { IsString, Length } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class NicknameDto { @IsString() + @Length(1, 16) @ApiProperty({ type: String, description: '사용자 닉네임' }) readonly nickname: string | null; } diff --git a/back/src/modules/user/dto/user.dto.ts b/back/src/modules/user/dto/user.dto.ts index d3a7871..d206c95 100644 --- a/back/src/modules/user/dto/user.dto.ts +++ b/back/src/modules/user/dto/user.dto.ts @@ -1,4 +1,12 @@ -import { IsString, IsNumber, IsNotEmpty } from '@nestjs/class-validator'; +import { + IsString, + IsNumber, + IsNotEmpty, + Length, + Min, + Max, + IsPositive +} from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class UserDto { @@ -8,25 +16,31 @@ export class UserDto { readonly id: number; @IsString() + @Length(1, 16) @IsNotEmpty() @ApiProperty({ type: String, description: '사용자 이름' }) readonly username: string; @IsString() + @Length(1, 16) @ApiProperty({ type: String, description: '사용자 닉네임' }) readonly nickname: string | null; @IsString() + @Length(1, 45) @IsNotEmpty() @ApiProperty({ type: String, description: 'Oauth에서 주는 값' }) readonly user_id: string; @IsNumber() + @IsPositive() + @Max(5) @IsNotEmpty() @ApiProperty({ type: Number, description: '스노우볼 갯수' }) readonly snowball_count: number; @IsNumber() + @Min(1) @ApiProperty({ type: Number, description: '메인 스노우볼 id' }) readonly main_snowball_id: number | null; @@ -38,6 +52,8 @@ export class UserDto { readonly snowball_list: number[]; @IsNumber() + @IsPositive() + @Max(150) @IsNotEmpty() @ApiProperty({ type: Number, description: '메시지 갯수' }) readonly message_count: number; diff --git a/back/src/modules/user/entity/user.entity.ts b/back/src/modules/user/entity/user.entity.ts index 610234c..56eac28 100644 --- a/back/src/modules/user/entity/user.entity.ts +++ b/back/src/modules/user/entity/user.entity.ts @@ -18,15 +18,12 @@ export class UserEntity { @Column({ length: 45 }) user_id: string; - // kakao, naver, google에서 주는 거임 @Column({ length: 16 }) username: string; - // 닉네임?? 16자? @Column({ length: 16, default: null }) nickname: string | null; - // kakao, naver, google @Column({ length: 6 }) provider: string; diff --git a/back/src/modules/user/user.service.ts b/back/src/modules/user/user.service.ts index 5d64133..d3aaf49 100644 --- a/back/src/modules/user/user.service.ts +++ b/back/src/modules/user/user.service.ts @@ -26,7 +26,11 @@ export class UserService { where: { user_id: user_id } }); if (exisitingUser) { - return {id:exisitingUser.id, name:exisitingUser.username, user_id:exisitingUser.user_id}; + return { + id: exisitingUser.id, + name: exisitingUser.username, + user_id: exisitingUser.user_id + }; } else { throw new NotFoundException('해당 유저를 찾을 수 없습니다.'); } @@ -82,12 +86,15 @@ export class UserService { return userDto; } - async updateNickname(id: number, nicknameDto: NicknameDto): Promise { + async updateNickname( + id: number, + nicknameDto: NicknameDto + ): Promise { const updateResult = await this.userRepository .createQueryBuilder() .update(UserEntity) .set({ - nickname:nicknameDto.nickname + nickname: nicknameDto.nickname }) .where('id = :id', { id: id }) .execute(); From fa66760906cb2a1b0f8a6ff41c27986f8e5a5810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 29 Nov 2023 10:49:21 +0900 Subject: [PATCH 134/185] =?UTF-8?q?feat:=20=EB=A9=94=EC=84=B8=EC=A7=80=20?= =?UTF-8?q?=EA=B0=9C=EC=88=98=20=EC=B4=88=EA=B3=BC=20conflict=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.service.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 8766e09..80e1c32 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -27,6 +27,8 @@ export class MessageService { user_id: number, snowball_id: number ): Promise { + if (!(await this.isInsertAllowed(snowball_id))) + throw new ConflictException('메세지 갯수가 30개를 초과했습니다'); const messageEntity = this.messageRepository.create({ user_id: user_id, snowball_id: snowball_id, @@ -49,6 +51,15 @@ export class MessageService { return resCreateMessage; } + + async isInsertAllowed(snowball_id: number): Promise { + const messageCount = await this.messageRepository.count({ + where: { snowball_id: snowball_id, is_deleted: false } + }); + if (messageCount >= 30) return false; + else return true; + } + async deleteMessage(user_id: number, message_id: number): Promise { try { const message = await this.messageRepository.findOne({ @@ -155,7 +166,9 @@ export class MessageService { } async getMessageCount(user_pk: number): Promise { - return this.messageRepository.count({ where: { user: { id: user_pk } } }); + return this.messageRepository.count({ + where: { user_id: user_pk, is_deleted: false } + }); } async getMessageList(snowball_id: number): Promise { From 9879f2819372fc4ff53c0ffcdc4b583c35291892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 29 Nov 2023 11:07:52 +0900 Subject: [PATCH 135/185] =?UTF-8?q?feat:=20decoration=5Fcoloe=20CHAR?= =?UTF-8?q?=ED=83=80=EC=9E=85=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/entity/message.entity.ts | 2 +- back/src/modules/snowball/entity/snowball.entity.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index b9a3f9f..61b0df8 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -23,7 +23,7 @@ export class MessageEntity { @Column() decoration_id: number; - @Column({ length: 7 }) + @Column({ type: 'char', length: 7 }) decoration_color: string; @Column() diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index 6809132..af8c7c6 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -27,7 +27,7 @@ export class SnowballEntity { @Column() main_decoration_id: number; - @Column() + @Column({ type: 'char', length: 7 }) main_decoration_color: string; @CreateDateColumn({ nullable: true, default: null }) From 4bfa3e28369869eee33ad6c0991b0b0f133dc008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 29 Nov 2023 11:07:52 +0900 Subject: [PATCH 136/185] =?UTF-8?q?feat:=20decoration=5Fcoloe=20CHAR?= =?UTF-8?q?=ED=83=80=EC=9E=85=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/entity/message.entity.ts | 2 +- back/src/modules/snowball/entity/snowball.entity.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/back/src/modules/message/entity/message.entity.ts b/back/src/modules/message/entity/message.entity.ts index b9a3f9f..61b0df8 100644 --- a/back/src/modules/message/entity/message.entity.ts +++ b/back/src/modules/message/entity/message.entity.ts @@ -23,7 +23,7 @@ export class MessageEntity { @Column() decoration_id: number; - @Column({ length: 7 }) + @Column({ type: 'char', length: 7 }) decoration_color: string; @Column() diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index 6809132..af8c7c6 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -27,7 +27,7 @@ export class SnowballEntity { @Column() main_decoration_id: number; - @Column() + @Column({ type: 'char', length: 7 }) main_decoration_color: string; @CreateDateColumn({ nullable: true, default: null }) From 57bea99dccd580a390cc237e6bf52459194675fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 29 Nov 2023 16:25:14 +0900 Subject: [PATCH 137/185] =?UTF-8?q?fix:=20=ED=94=84=EB=A1=A0=ED=8A=B8=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.service.ts | 15 +++++++++++++-- back/src/modules/snowball/snowball.controller.ts | 8 ++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 80e1c32..5885f98 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -171,9 +171,20 @@ export class MessageService { }); } - async getMessageList(snowball_id: number): Promise { + async getMessageList(snowball_id: number): Promise { const messages = await this.messageRepository.find({ - where: { snowball_id: snowball_id, is_deleted: false } + where: { snowball_id: snowball_id, is_deleted: false }, + select: [ + 'id', + 'decoration_id', + 'decoration_color', + 'letter_id', + 'content', + 'sender', + 'opened', + 'created', + 'location' + ] }); return messages; } diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index 2ab0ae9..7efecc8 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -26,12 +26,12 @@ import { JWTGuard } from '../auth/auth.guard'; import { UpdateMainDecoDto } from './dto/update-main-decoration.dto'; @ApiTags('Snowball API') -@UseGuards(JWTGuard) -@ApiBearerAuth('jwt-token') @Controller('snowball') export class SnowballController { constructor(private readonly snowballService: SnowballService) {} + @UseGuards(JWTGuard) + @ApiBearerAuth('jwt-token') @Post() @HttpCode(201) @ApiOperation({ @@ -54,6 +54,8 @@ export class SnowballController { return snowball; } + @UseGuards(JWTGuard) + @ApiBearerAuth('jwt-token') @Put('/:snowball_id') @HttpCode(200) @ApiResponse({ @@ -93,6 +95,8 @@ export class SnowballController { return snowball; } + @UseGuards(JWTGuard) + @ApiBearerAuth('jwt-token') @Put('/:snowball_id/decoration') @ApiResponse({ status: 200, From ae747587615d41422afe9b41f2c574cac4e45a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 29 Nov 2023 16:29:53 +0900 Subject: [PATCH 138/185] =?UTF-8?q?fix:=20console.log=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/message.service.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 5885f98..caea75c 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -85,7 +85,6 @@ export class MessageService { } async getAllMessages(user_id: number): Promise { - //To Do: query builder로 개선하기 const messages: MessageEntity[] = await this.messageRepository.find({ where: { user_id: user_id, is_deleted: false } }); @@ -134,7 +133,6 @@ export class MessageService { }) .where('id = :id', { id: message_id }) .execute(); - console.log(updateResult); if (!updateResult.affected) { throw new NotFoundException('업데이트할 메시지가 존재하지 않습니다.'); } else if (updateResult.affected > 1) { From 5f93b6a834ad2b0bd018d1bb7e3a0d57ee608a03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 29 Nov 2023 17:47:08 +0900 Subject: [PATCH 139/185] =?UTF-8?q?feat:=20=EB=B9=84=EA=B3=B5=EA=B0=9C=20?= =?UTF-8?q?=EB=A9=94=EC=84=B8=EC=A7=80=20=EC=84=A4=EC=A0=95=20&=20?= =?UTF-8?q?=EB=94=94=EB=A0=89=ED=86=A0=EB=A6=AC=20=EA=B5=AC=EC=A1=B0=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/common/guards/hasJwt.guard.ts | 24 +++++++++++++++++++ .../guards/jwt.guard.ts} | 0 back/src/{ => common}/util/swagger.ts | 0 back/src/main.ts | 2 +- back/src/modules/auth/auth.module.ts | 2 +- .../src/modules/message/message.controller.ts | 2 +- back/src/modules/message/message.module.ts | 2 +- back/src/modules/message/message.service.ts | 11 ++++++++- .../modules/snowball/snowball.controller.ts | 15 +++++++++--- back/src/modules/snowball/snowball.module.ts | 5 ++-- back/src/modules/snowball/snowball.service.ts | 16 +++++++++---- back/src/modules/user/user.controller.ts | 2 +- back/src/modules/user/user.module.ts | 2 +- 13 files changed, 67 insertions(+), 16 deletions(-) create mode 100644 back/src/common/guards/hasJwt.guard.ts rename back/src/{modules/auth/auth.guard.ts => common/guards/jwt.guard.ts} (100%) rename back/src/{ => common}/util/swagger.ts (100%) diff --git a/back/src/common/guards/hasJwt.guard.ts b/back/src/common/guards/hasJwt.guard.ts new file mode 100644 index 0000000..e7c4829 --- /dev/null +++ b/back/src/common/guards/hasJwt.guard.ts @@ -0,0 +1,24 @@ +import { CanActivate, ExecutionContext, Injectable, Req } from '@nestjs/common'; +import { JwtService } from '@nestjs/jwt'; +import { Request } from 'express'; + +@Injectable() +export class hasJWTGuard implements CanActivate { + constructor(private readonly jwtService: JwtService) {} + + async canActivate(context: ExecutionContext): Promise { + const request = context.switchToHttp().getRequest(); + const token = this.extractTokenFromHeader(request); + if (!token) { + request['hasToken'] = false; + } else { + request['hasToken'] = true; + } + return true; + } + + private extractTokenFromHeader(@Req() req: Request): string | undefined { + const [type, token] = req.headers.authorization?.split(' ') ?? []; + return type === 'Bearer' ? token : undefined; + } +} diff --git a/back/src/modules/auth/auth.guard.ts b/back/src/common/guards/jwt.guard.ts similarity index 100% rename from back/src/modules/auth/auth.guard.ts rename to back/src/common/guards/jwt.guard.ts diff --git a/back/src/util/swagger.ts b/back/src/common/util/swagger.ts similarity index 100% rename from back/src/util/swagger.ts rename to back/src/common/util/swagger.ts diff --git a/back/src/main.ts b/back/src/main.ts index a8957bc..e7acedd 100644 --- a/back/src/main.ts +++ b/back/src/main.ts @@ -1,5 +1,5 @@ import { NestFactory } from '@nestjs/core'; -import { setupSwagger } from 'src/util/swagger'; +import { setupSwagger } from 'src/common/util/swagger'; import { AppModule } from './app.module'; import { ValidationPipe } from '@nestjs/common/pipes'; diff --git a/back/src/modules/auth/auth.module.ts b/back/src/modules/auth/auth.module.ts index a64c23e..398afdd 100644 --- a/back/src/modules/auth/auth.module.ts +++ b/back/src/modules/auth/auth.module.ts @@ -7,7 +7,7 @@ import { PassportModule } from '@nestjs/passport'; import { AuthService } from './auth.service'; import { TypeOrmModule } from '@nestjs/typeorm'; import { UserEntity } from '../user/entity/user.entity'; -import { JWTGuard } from './auth.guard'; +import { JWTGuard } from '../../common/guards/jwt.guard'; import { JwtModule } from '@nestjs/jwt'; @Module({ diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 021fd5b..0fe2dac 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -27,7 +27,7 @@ import { } from '@nestjs/swagger'; import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; import { MessageDto } from './dto/message.dto'; -import { JWTGuard } from '../auth/auth.guard'; +import { JWTGuard } from 'src/common/guards/jwt.guard'; import { UpdateMessageDecorationDto } from './dto/update-message-decoration.dto'; import { UpdateMessageLocationDto } from './dto/update-message-location.dto'; @ApiTags('Message API') diff --git a/back/src/modules/message/message.module.ts b/back/src/modules/message/message.module.ts index 62d9847..458c02d 100644 --- a/back/src/modules/message/message.module.ts +++ b/back/src/modules/message/message.module.ts @@ -3,7 +3,7 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { MessageController } from './message.controller'; import { MessageService } from './message.service'; import { MessageEntity } from './entity/message.entity'; -import { JWTGuard } from '../auth/auth.guard'; +import { JWTGuard } from '../../common/guards/jwt.guard'; @Module({ imports: [TypeOrmModule.forFeature([MessageEntity])], controllers: [MessageController], diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index caea75c..c93bc7d 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -169,7 +169,10 @@ export class MessageService { }); } - async getMessageList(snowball_id: number): Promise { + async getMessageList( + snowball_id: number, + is_private_contents: boolean + ): Promise { const messages = await this.messageRepository.find({ where: { snowball_id: snowball_id, is_deleted: false }, select: [ @@ -184,6 +187,12 @@ export class MessageService { 'location' ] }); + if (is_private_contents) { + messages.map(message => { + message.content = '비공개 메세지'; + message.sender = '비공개 발신자'; + }); + } return messages; } } diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index 7efecc8..b442ee0 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -22,7 +22,8 @@ import { ReqCreateSnowballDto } from './dto/request/req-create-snowball.dto'; import { ReqUpdateSnowballDto } from './dto/request/req-update-snowball.dto'; import { SnowballDto } from './dto/snowball.dto'; import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; -import { JWTGuard } from '../auth/auth.guard'; +import { JWTGuard } from 'src/common/guards/jwt.guard'; +import { hasJWTGuard } from 'src/common/guards/hasJwt.guard'; import { UpdateMainDecoDto } from './dto/update-main-decoration.dto'; @ApiTags('Snowball API') @@ -80,6 +81,8 @@ export class SnowballController { } @Get('/:snowball_id') + @UseGuards(hasJWTGuard) + @ApiBearerAuth('jwt-token') @HttpCode(200) @ApiResponse({ status: 200, @@ -90,8 +93,14 @@ export class SnowballController { summary: '스노우볼 조회 API', description: '스노우볼의 정보를 조회합니다.' }) - async getSnowball(@Param('snowball_id') snowball_id: number) { - const snowball = await this.snowballService.getSnowball(snowball_id); + async getSnowball( + @Req() req: any, + @Param('snowball_id') snowball_id: number + ) { + const snowball = await this.snowballService.getSnowball( + snowball_id, + req.hasToken + ); return snowball; } diff --git a/back/src/modules/snowball/snowball.module.ts b/back/src/modules/snowball/snowball.module.ts index 2a4a52e..815ed7b 100644 --- a/back/src/modules/snowball/snowball.module.ts +++ b/back/src/modules/snowball/snowball.module.ts @@ -4,7 +4,8 @@ import { SnowballService } from './snowball.service'; import { MessageModule } from '../message/message.module'; import { TypeOrmModule } from '@nestjs/typeorm'; import { SnowballEntity } from './entity/snowball.entity'; -import { JWTGuard } from '../auth/auth.guard'; +import { JWTGuard } from '../../common/guards/jwt.guard'; +import { hasJWTGuard } from 'src/common/guards/hasJwt.guard'; import { MessageEntity } from '../message/entity/message.entity'; import { MessageService } from '../message/message.service'; @@ -14,7 +15,7 @@ import { MessageService } from '../message/message.service'; MessageModule ], controllers: [SnowballController], - providers: [SnowballService, MessageService, JWTGuard], + providers: [SnowballService, MessageService, JWTGuard, hasJWTGuard], exports: [SnowballService, MessageService, TypeOrmModule] }) export class SnowballModule {} diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index f311208..3e2fe22 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -78,21 +78,29 @@ export class SnowballService { return resUpdateSnowballDto; } - async getSnowball(snowball_id: number): Promise | null { + async getSnowball( + snowball_id: number, + hasToken: boolean + ): Promise | null { const snowball = await this.snowballRepository.findOne({ where: { id: snowball_id } }); if (!snowball) { return null; } + const is_message_private = snowball.message_private ? true : false; + const is_private_contents: boolean = !hasToken && is_message_private; const resSnowball: SnowballDto = { id: snowball.id, title: snowball.title, main_decoration_id: snowball.main_decoration_id, main_decoration_color: snowball.main_decoration_color, - is_message_private: snowball.message_private ? true : false, - message_list: await this.messageService.getMessageList(snowball.id) + is_message_private: is_message_private, + message_list: await this.messageService.getMessageList( + snowball.id, + is_private_contents + ) }; return resSnowball; @@ -124,7 +132,7 @@ export class SnowballService { if (!userDto.main_snowball_id) { return null; } else { - return await this.getSnowball(userDto.main_snowball_id); + return await this.getSnowball(userDto.main_snowball_id, true); } } diff --git a/back/src/modules/user/user.controller.ts b/back/src/modules/user/user.controller.ts index 14219f6..45ac2ca 100644 --- a/back/src/modules/user/user.controller.ts +++ b/back/src/modules/user/user.controller.ts @@ -7,7 +7,7 @@ import { Req, Put } from '@nestjs/common'; -import { JWTGuard } from '../auth/auth.guard'; +import { JWTGuard } from '../../common/guards/jwt.guard'; import { ApiTags, ApiOperation, diff --git a/back/src/modules/user/user.module.ts b/back/src/modules/user/user.module.ts index f2cb99c..67b436c 100644 --- a/back/src/modules/user/user.module.ts +++ b/back/src/modules/user/user.module.ts @@ -4,7 +4,7 @@ import { UserController } from './user.controller'; import { UserEntity } from './entity/user.entity'; import { TypeOrmModule } from '@nestjs/typeorm'; import { SnowballModule } from '../snowball/snowball.module'; -import { JWTGuard } from '../auth/auth.guard'; +import { JWTGuard } from '../../common/guards/jwt.guard'; import { SnowballEntity } from '../snowball/entity/snowball.entity'; import { MessageEntity } from '../message/entity/message.entity'; import { SnowballService } from '../snowball/snowball.service'; From d9299a3eb1e2e7d6dfcbe551554bd385a8f17ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 29 Nov 2023 22:22:47 +0900 Subject: [PATCH 140/185] =?UTF-8?q?fix:=20=ED=8F=B4=EB=8D=94=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/common/guards/hasJwt.guard.ts | 5 ++-- back/src/common/guards/jwt.guard.ts | 1 + .../strategy/google-auth.strategy.ts | 0 .../strategy/kakao-auth.strategy.ts | 0 .../strategy/naver-auth.strategy.ts | 0 back/src/modules/auth/auth.module.ts | 6 ++--- .../dto/request/req-create-message.dto.ts | 7 ----- back/src/modules/message/message.service.ts | 26 ++++++++++++++----- back/src/modules/snowball/snowball.service.ts | 11 ++++---- 9 files changed, 32 insertions(+), 24 deletions(-) rename back/src/{modules/auth => common}/strategy/google-auth.strategy.ts (100%) rename back/src/{modules/auth => common}/strategy/kakao-auth.strategy.ts (100%) rename back/src/{modules/auth => common}/strategy/naver-auth.strategy.ts (100%) diff --git a/back/src/common/guards/hasJwt.guard.ts b/back/src/common/guards/hasJwt.guard.ts index e7c4829..964671d 100644 --- a/back/src/common/guards/hasJwt.guard.ts +++ b/back/src/common/guards/hasJwt.guard.ts @@ -1,10 +1,9 @@ import { CanActivate, ExecutionContext, Injectable, Req } from '@nestjs/common'; -import { JwtService } from '@nestjs/jwt'; import { Request } from 'express'; @Injectable() export class hasJWTGuard implements CanActivate { - constructor(private readonly jwtService: JwtService) {} + constructor() {} async canActivate(context: ExecutionContext): Promise { const request = context.switchToHttp().getRequest(); @@ -22,3 +21,5 @@ export class hasJWTGuard implements CanActivate { return type === 'Bearer' ? token : undefined; } } + +// 인터셉터, class-trasformer로 변경 diff --git a/back/src/common/guards/jwt.guard.ts b/back/src/common/guards/jwt.guard.ts index 40dc7e5..efb6a0a 100644 --- a/back/src/common/guards/jwt.guard.ts +++ b/back/src/common/guards/jwt.guard.ts @@ -22,6 +22,7 @@ export class JWTGuard implements CanActivate { const payload = await this.jwtService.verify(token, { secret: process.env.JWT_ACCESS_SECRET }); + request['id'] = payload.id; request['name'] = payload.name; request['user_id'] = payload.user_id; diff --git a/back/src/modules/auth/strategy/google-auth.strategy.ts b/back/src/common/strategy/google-auth.strategy.ts similarity index 100% rename from back/src/modules/auth/strategy/google-auth.strategy.ts rename to back/src/common/strategy/google-auth.strategy.ts diff --git a/back/src/modules/auth/strategy/kakao-auth.strategy.ts b/back/src/common/strategy/kakao-auth.strategy.ts similarity index 100% rename from back/src/modules/auth/strategy/kakao-auth.strategy.ts rename to back/src/common/strategy/kakao-auth.strategy.ts diff --git a/back/src/modules/auth/strategy/naver-auth.strategy.ts b/back/src/common/strategy/naver-auth.strategy.ts similarity index 100% rename from back/src/modules/auth/strategy/naver-auth.strategy.ts rename to back/src/common/strategy/naver-auth.strategy.ts diff --git a/back/src/modules/auth/auth.module.ts b/back/src/modules/auth/auth.module.ts index 398afdd..f27ee61 100644 --- a/back/src/modules/auth/auth.module.ts +++ b/back/src/modules/auth/auth.module.ts @@ -1,7 +1,7 @@ import { Module } from '@nestjs/common'; -import { GoogleAuthStrategy } from './strategy/google-auth.strategy'; -import { NaverAuthStrategy } from './strategy/naver-auth.strategy'; -import { KakaoAuthStrategy } from './strategy/kakao-auth.strategy'; +import { GoogleAuthStrategy } from '../../common/strategy/google-auth.strategy'; +import { NaverAuthStrategy } from '../../common/strategy/naver-auth.strategy'; +import { KakaoAuthStrategy } from '../../common/strategy/kakao-auth.strategy'; import { AuthController } from './auth.controller'; import { PassportModule } from '@nestjs/passport'; import { AuthService } from './auth.service'; diff --git a/back/src/modules/message/dto/request/req-create-message.dto.ts b/back/src/modules/message/dto/request/req-create-message.dto.ts index 2eb20db..ecf66a4 100644 --- a/back/src/modules/message/dto/request/req-create-message.dto.ts +++ b/back/src/modules/message/dto/request/req-create-message.dto.ts @@ -34,13 +34,6 @@ export class ReqCreateMessageDto { @ApiProperty({ type: String, description: '장식 색상', example: '#FFFFFF' }) readonly decoration_color: string; - @IsNumber() - @Min(1) - @Max(72) - @IsNotEmpty() - @ApiProperty({ type: Number, description: '장식 위치', example: 1 }) - readonly location: number; - @IsNumber() @Min(1) @Max(3) diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index c93bc7d..a67295e 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -36,17 +36,18 @@ export class MessageService { content: createMessageDto.content, decoration_id: createMessageDto.decoration_id, decoration_color: createMessageDto.decoration_color, - location: createMessageDto.location, + location: await this.findLocation(user_id), letter_id: createMessageDto.letter_id, opened: null // is_deleted랑 created는 자동으로 설정 }); - const savedMessage = await this.messageRepository.save(messageEntity); - + const savedMessage = await this.messageRepository.insert(messageEntity); + if (!savedMessage.raw.affectedRows) + throw new InternalServerErrorException('insert fail'); // 이 부분에서 필터링 로직을 작성 const resCreateMessage: ResCreateMessageDto = { - sender: savedMessage.sender, - content: savedMessage.content + sender: createMessageDto.sender, + content: createMessageDto.content }; return resCreateMessage; @@ -88,7 +89,7 @@ export class MessageService { const messages: MessageEntity[] = await this.messageRepository.find({ where: { user_id: user_id, is_deleted: false } }); - + // To Do: 인터셉터 if (!messages) { throw new NotFoundException(`User with id ${user_id} not found`); } @@ -100,7 +101,7 @@ export class MessageService { const message = await this.messageRepository.findOne({ where: { id: message_id } }); - console.log(message); + // 커스텀 데코레이터로 if (!message) { throw new NotFoundException( `${message_id}번 메시지를 찾을 수 없었습니다.` @@ -195,4 +196,15 @@ export class MessageService { } return messages; } + async findLocation(user_id: number): Promise { + const message = await this.messageRepository.findOne({ + where: { user_id: user_id }, + select: ['location'], + order: { + location: 'ASC' + } + }); + console.log(message); + return message.location; + } } diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 3e2fe22..8f636e6 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -89,7 +89,7 @@ export class SnowballService { return null; } const is_message_private = snowball.message_private ? true : false; - const is_private_contents: boolean = !hasToken && is_message_private; + const is_private_contents = !hasToken && is_message_private; const resSnowball: SnowballDto = { id: snowball.id, @@ -141,13 +141,14 @@ export class SnowballService { where: { user_id: user_pk } }); - if (snowballs[0].length > 0) { - const snowball_list = snowballs[0].map(snowball => snowball.id); + const [items = [], count = 0] = snowballs; + if (count > 0) { + const snowball_list = items.map(snowball => snowball.id); return { - snowball_count: snowballs[1], + snowball_count: count, message_count: await this.messageService.getMessageCount(user_pk), snowball_list, - main_snowball_id: snowballs[0][0].id + main_snowball_id: items[0].id }; } else { return { From 1570a55a348ea9dab890e90e1f275743a8c9a5fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 29 Nov 2023 22:29:04 +0900 Subject: [PATCH 141/185] =?UTF-8?q?feat:=20=EC=8A=A4=EB=85=B8=EC=9A=B0?= =?UTF-8?q?=EB=B3=BC=20=EB=B0=A9=EB=AC=B8=EC=9E=90=20=EB=A9=94=EC=84=B8?= =?UTF-8?q?=EC=A7=80=20private=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/snowball/snowball.service.ts | 7 +++++-- back/src/modules/user/user.controller.ts | 4 ++-- back/src/modules/user/user.service.ts | 8 +++++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 8f636e6..e045a0f 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -128,11 +128,14 @@ export class SnowballService { return updateMainDecoDto; } - async getMainSnowballDto(userDto: UserDto): Promise { + async getMainSnowballDto( + userDto: UserDto, + hasToken: boolean + ): Promise { if (!userDto.main_snowball_id) { return null; } else { - return await this.getSnowball(userDto.main_snowball_id, true); + return await this.getSnowball(userDto.main_snowball_id, hasToken); } } diff --git a/back/src/modules/user/user.controller.ts b/back/src/modules/user/user.controller.ts index 45ac2ca..c7f0ca3 100644 --- a/back/src/modules/user/user.controller.ts +++ b/back/src/modules/user/user.controller.ts @@ -36,7 +36,7 @@ export class UserController { type: ResInfoDto }) async createUserInfo(@Req() req: any): Promise { - const result = this.userService.createUserInfo(req); + const result = this.userService.createUserInfo(req, true); return result; } @@ -54,7 +54,7 @@ export class UserController { @Param('user_id') user_id: string ): Promise { const userData = await this.userService.getUserData(user_id); - const result = this.userService.createUserInfo(userData); + const result = this.userService.createUserInfo(userData, false); return result; } diff --git a/back/src/modules/user/user.service.ts b/back/src/modules/user/user.service.ts index d3aaf49..ca66513 100644 --- a/back/src/modules/user/user.service.ts +++ b/back/src/modules/user/user.service.ts @@ -47,14 +47,16 @@ export class UserService { } } - async createUserInfo(user: any): Promise { + async createUserInfo(user: any, hasToken: boolean): Promise { const userDto: UserDto = await this.createUserDto( user.id, user.name, user.user_id ); - const mainSnowballDto = - await this.snowballService.getMainSnowballDto(userDto); + const mainSnowballDto = await this.snowballService.getMainSnowballDto( + userDto, + hasToken + ); const resInfoDto: ResInfoDto = { user: userDto, From 49d63bec484392243d0d9116c81d07f64d85b3dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 29 Nov 2023 22:47:41 +0900 Subject: [PATCH 142/185] =?UTF-8?q?feat:=20location=20=EC=9E=90=EB=8F=99?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/res-create-message.dto.ts | 15 ++++++++- back/src/modules/message/message.service.ts | 32 +++++++++++++------ 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/back/src/modules/message/dto/response/res-create-message.dto.ts b/back/src/modules/message/dto/response/res-create-message.dto.ts index e8b7cd9..69248c7 100644 --- a/back/src/modules/message/dto/response/res-create-message.dto.ts +++ b/back/src/modules/message/dto/response/res-create-message.dto.ts @@ -1,4 +1,11 @@ -import { IsString, IsNotEmpty, Length } from '@nestjs/class-validator'; +import { + IsString, + IsNotEmpty, + Length, + IsNumber, + Min, + Max +} from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class ResCreateMessageDto { @@ -16,4 +23,10 @@ export class ResCreateMessageDto { @IsNotEmpty() @ApiProperty({ type: String, description: '필터링된 메세지 내용' }) readonly content: string; + + @IsNumber() + @Min(1) + @Max(72) + @ApiProperty({ type: Number, description: '메세지 위치' }) + readonly location: number; } diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index a67295e..2844ae1 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -29,6 +29,8 @@ export class MessageService { ): Promise { if (!(await this.isInsertAllowed(snowball_id))) throw new ConflictException('메세지 갯수가 30개를 초과했습니다'); + + const location = await this.findLocation(user_id); const messageEntity = this.messageRepository.create({ user_id: user_id, snowball_id: snowball_id, @@ -36,7 +38,7 @@ export class MessageService { content: createMessageDto.content, decoration_id: createMessageDto.decoration_id, decoration_color: createMessageDto.decoration_color, - location: await this.findLocation(user_id), + location: location, letter_id: createMessageDto.letter_id, opened: null // is_deleted랑 created는 자동으로 설정 @@ -47,7 +49,8 @@ export class MessageService { // 이 부분에서 필터링 로직을 작성 const resCreateMessage: ResCreateMessageDto = { sender: createMessageDto.sender, - content: createMessageDto.content + content: createMessageDto.content, + location: location }; return resCreateMessage; @@ -197,14 +200,23 @@ export class MessageService { return messages; } async findLocation(user_id: number): Promise { - const message = await this.messageRepository.findOne({ - where: { user_id: user_id }, - select: ['location'], - order: { - location: 'ASC' + const findLocations = this.messageRepository + .createQueryBuilder('message') + .select('location') + .where('user_id = :user_id', { user_id }) + .andWhere('is_deleted = false'); + const locations = await findLocations.getRawMany(); + + let firstEmptyLocation: number | null = null; + for (let i = 1; i <= 30; i++) { + const exists = locations.some(result => result.location === i); + if (!exists) { + firstEmptyLocation = i; + break; } - }); - console.log(message); - return message.location; + } + if (firstEmptyLocation === null) + throw new ConflictException('location에 빈자리가 없습니다'); + return firstEmptyLocation; } } From 9c122e888cf17f988e685cdb4154c761d906ab9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Wed, 29 Nov 2023 22:50:34 +0900 Subject: [PATCH 143/185] =?UTF-8?q?docs:=20sample=20interceptor=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/interceptors/sample.intercepotr.ts | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 back/src/common/interceptors/sample.intercepotr.ts diff --git a/back/src/common/interceptors/sample.intercepotr.ts b/back/src/common/interceptors/sample.intercepotr.ts new file mode 100644 index 0000000..70073dd --- /dev/null +++ b/back/src/common/interceptors/sample.intercepotr.ts @@ -0,0 +1,22 @@ +import { + Injectable, + NestInterceptor, + ExecutionContext, + CallHandler +} from '@nestjs/common'; +import { Observable } from 'rxjs'; +import { tap } from 'rxjs/operators'; + +@Injectable() +export class SampleInterceptor implements NestInterceptor { + intercept(context: ExecutionContext, next: CallHandler): Observable { + console.log('Before...'); + + // 여기에 원하는 로직 추가 가능 + + const now = Date.now(); + return next + .handle() + .pipe(tap(() => console.log(`After... ${Date.now() - now}ms`))); + } +} From 1cd949634d0c4904196a2d07dbd6638a1f216ad6 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Thu, 30 Nov 2023 13:41:41 +0900 Subject: [PATCH 144/185] =?UTF-8?q?fix:=20whitelist=20=EC=86=8D=EC=84=B1?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/common/guards/hasJwt.guard.ts | 2 +- back/src/main.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/back/src/common/guards/hasJwt.guard.ts b/back/src/common/guards/hasJwt.guard.ts index 964671d..a28c290 100644 --- a/back/src/common/guards/hasJwt.guard.ts +++ b/back/src/common/guards/hasJwt.guard.ts @@ -22,4 +22,4 @@ export class hasJWTGuard implements CanActivate { } } -// 인터셉터, class-trasformer로 변경 +// 커스텀데코레이터, class-trasformer로 변경 diff --git a/back/src/main.ts b/back/src/main.ts index e7acedd..61c2d9b 100644 --- a/back/src/main.ts +++ b/back/src/main.ts @@ -9,7 +9,8 @@ async function bootstrap() { app.useGlobalPipes( new ValidationPipe({ forbidNonWhitelisted: true, - forbidUnknownValues: true + forbidUnknownValues: true, + whitelist: true }) ); setupSwagger(app); From 64c79e7c45ca88e43bd497a8c9d4ba08832cb692 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Thu, 30 Nov 2023 14:24:42 +0900 Subject: [PATCH 145/185] =?UTF-8?q?feat:=20request=20=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/common/guards/jwt.guard.ts | 4 +--- back/src/common/interface/request.interface.ts | 9 +++++++++ back/src/modules/message/message.controller.ts | 9 +++++---- back/src/modules/snowball/snowball.controller.ts | 6 ++++-- back/src/modules/user/user.controller.ts | 9 +++++---- 5 files changed, 24 insertions(+), 13 deletions(-) create mode 100644 back/src/common/interface/request.interface.ts diff --git a/back/src/common/guards/jwt.guard.ts b/back/src/common/guards/jwt.guard.ts index efb6a0a..0704186 100644 --- a/back/src/common/guards/jwt.guard.ts +++ b/back/src/common/guards/jwt.guard.ts @@ -23,9 +23,7 @@ export class JWTGuard implements CanActivate { secret: process.env.JWT_ACCESS_SECRET }); - request['id'] = payload.id; - request['name'] = payload.name; - request['user_id'] = payload.user_id; + request['user'] = payload; } catch { throw new UnauthorizedException(); } diff --git a/back/src/common/interface/request.interface.ts b/back/src/common/interface/request.interface.ts new file mode 100644 index 0000000..71c1b27 --- /dev/null +++ b/back/src/common/interface/request.interface.ts @@ -0,0 +1,9 @@ +import Request from 'express'; + +export interface JWTRequest extends Request { + user: { + id: number; + name: string; + user_id: string; + }; +} diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 0fe2dac..768e312 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -30,6 +30,7 @@ import { MessageDto } from './dto/message.dto'; import { JWTGuard } from 'src/common/guards/jwt.guard'; import { UpdateMessageDecorationDto } from './dto/update-message-decoration.dto'; import { UpdateMessageLocationDto } from './dto/update-message-location.dto'; +import { JWTRequest } from 'src/common/interface/request.interface'; @ApiTags('Message API') @Controller('message') export class MessageController { @@ -83,10 +84,10 @@ export class MessageController { description: '로그인이 필요합니다.' }) async deleteMessage( - @Req() req: any, + @Req() req: JWTRequest, @Param('message_id') message_id: number ) { - await this.messageService.deleteMessage(req.id, message_id); + await this.messageService.deleteMessage(req.user.id, message_id); } @UseGuards(JWTGuard) @@ -106,8 +107,8 @@ export class MessageController { status: 500, description: 'Find Fail' }) - async getAllMessages(@Req() req: any): Promise { - const messages = await this.messageService.getAllMessages(req.id); + async getAllMessages(@Req() req: JWTRequest): Promise { + const messages = await this.messageService.getAllMessages(req.user.id); return messages; } diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index b442ee0..8fcfbac 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -25,6 +25,7 @@ import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; import { JWTGuard } from 'src/common/guards/jwt.guard'; import { hasJWTGuard } from 'src/common/guards/hasJwt.guard'; import { UpdateMainDecoDto } from './dto/update-main-decoration.dto'; +import { JWTRequest } from '../../common/interface/request.interface'; @ApiTags('Snowball API') @Controller('snowball') @@ -45,11 +46,11 @@ export class SnowballController { }) @ApiBody({ type: ReqCreateSnowballDto }) createSnowball( - @Req() req: any, + @Req() req: JWTRequest, @Body() createSnowballDto: ReqCreateSnowballDto ): Promise { const snowball = this.snowballService.createSnowball( - req.id, + req.user.id, createSnowballDto ); return snowball; @@ -94,6 +95,7 @@ export class SnowballController { description: '스노우볼의 정보를 조회합니다.' }) async getSnowball( + //TODO change to JWTRequest type @Req() req: any, @Param('snowball_id') snowball_id: number ) { diff --git a/back/src/modules/user/user.controller.ts b/back/src/modules/user/user.controller.ts index c7f0ca3..fb4090f 100644 --- a/back/src/modules/user/user.controller.ts +++ b/back/src/modules/user/user.controller.ts @@ -18,6 +18,7 @@ import { import { UserService } from './user.service'; import { ResInfoDto } from './dto/response/res-info.dto'; import { NicknameDto } from './dto/nickname.dto'; +import { JWTRequest } from 'src/common/interface/request.interface'; @ApiTags('User API') @Controller('user') @@ -35,8 +36,8 @@ export class UserController { status: 200, type: ResInfoDto }) - async createUserInfo(@Req() req: any): Promise { - const result = this.userService.createUserInfo(req, true); + async createUserInfo(@Req() req: JWTRequest): Promise { + const result = this.userService.createUserInfo(req.user, true); return result; } @@ -72,10 +73,10 @@ export class UserController { type: NicknameDto }) async updateNickname( - @Req() req: any, + @Req() req: JWTRequest, @Body() nicknameDto: NicknameDto ): Promise { - const result = this.userService.updateNickname(req.id, nicknameDto); + const result = this.userService.updateNickname(req.user.id, nicknameDto); return result; } } From 197ff97bf522da953c6fef21e6e02326c377fb3d Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Thu, 30 Nov 2023 14:51:33 +0900 Subject: [PATCH 146/185] =?UTF-8?q?feat:=20hasToken=20=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/common/interface/request.interface.ts | 6 +++++- back/src/modules/snowball/snowball.controller.ts | 8 +++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/back/src/common/interface/request.interface.ts b/back/src/common/interface/request.interface.ts index 71c1b27..8a9a1a6 100644 --- a/back/src/common/interface/request.interface.ts +++ b/back/src/common/interface/request.interface.ts @@ -1,4 +1,4 @@ -import Request from 'express'; +import { Request } from 'express'; export interface JWTRequest extends Request { user: { @@ -7,3 +7,7 @@ export interface JWTRequest extends Request { user_id: string; }; } + +export interface hasTokenRequest extends Request { + hasToken: boolean; +} diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index 8fcfbac..88ff4eb 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -25,7 +25,10 @@ import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; import { JWTGuard } from 'src/common/guards/jwt.guard'; import { hasJWTGuard } from 'src/common/guards/hasJwt.guard'; import { UpdateMainDecoDto } from './dto/update-main-decoration.dto'; -import { JWTRequest } from '../../common/interface/request.interface'; +import { + JWTRequest, + hasTokenRequest +} from '../../common/interface/request.interface'; @ApiTags('Snowball API') @Controller('snowball') @@ -95,8 +98,7 @@ export class SnowballController { description: '스노우볼의 정보를 조회합니다.' }) async getSnowball( - //TODO change to JWTRequest type - @Req() req: any, + @Req() req: hasTokenRequest, @Param('snowball_id') snowball_id: number ) { const snowball = await this.snowballService.getSnowball( From c47c1dcca1e474b8d452da72418569539403a0c2 Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 30 Nov 2023 14:24:18 +0900 Subject: [PATCH 147/185] =?UTF-8?q?feat:=20=EC=8A=A4=EB=85=B8=EC=9A=B0?= =?UTF-8?q?=EB=B3=BC=20=EC=84=9C=EB=B9=84=EC=8A=A4=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=B4=EC=84=9C=20circular=20dependency=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/snowball/snowball.module.ts | 6 ++-- back/src/modules/snowball/snowball.service.ts | 34 ++++++++++++++----- back/src/modules/user/user.module.ts | 7 ++-- back/src/modules/user/user.service.ts | 8 ++++- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/back/src/modules/snowball/snowball.module.ts b/back/src/modules/snowball/snowball.module.ts index 815ed7b..513516c 100644 --- a/back/src/modules/snowball/snowball.module.ts +++ b/back/src/modules/snowball/snowball.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { Module, forwardRef } from '@nestjs/common'; import { SnowballController } from './snowball.controller'; import { SnowballService } from './snowball.service'; import { MessageModule } from '../message/message.module'; @@ -8,11 +8,13 @@ import { JWTGuard } from '../../common/guards/jwt.guard'; import { hasJWTGuard } from 'src/common/guards/hasJwt.guard'; import { MessageEntity } from '../message/entity/message.entity'; import { MessageService } from '../message/message.service'; +import { UserModule } from '../user/user.module'; @Module({ imports: [ TypeOrmModule.forFeature([SnowballEntity, MessageEntity]), - MessageModule + MessageModule, + forwardRef(() => UserModule) ], controllers: [SnowballController], providers: [SnowballService, MessageService, JWTGuard, hasJWTGuard], diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index e045a0f..aea2e6f 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -1,4 +1,10 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; +import { + BadRequestException, + Inject, + Injectable, + NotFoundException, + forwardRef +} from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { SnowballEntity } from './entity/snowball.entity'; @@ -9,6 +15,7 @@ import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; import { UpdateMainDecoDto } from './dto/update-main-decoration.dto'; import { UserDto } from '../user/dto/user.dto'; import { MessageService } from '../message/message.service'; +import { UserService } from '../user/user.service'; export interface SnowballInfo { snowball_count: number; @@ -21,6 +28,8 @@ export interface SnowballInfo { export class SnowballService { constructor( private readonly messageService: MessageService, + @Inject(forwardRef(() => UserService)) + private readonly userService: UserService, @InjectRepository(SnowballEntity) private readonly snowballRepository: Repository ) {} @@ -29,20 +38,27 @@ export class SnowballService { userid: number, createSnowballDto: ReqCreateSnowballDto ): Promise { + // 유저있는지 확인 + const user = await this.userService.getUserData(userid.toString()); + // create a new snowball if user has less than 5 snowballs + const userSnowballCount = await this.snowballRepository.count({ + where: { user_id: user.id } + }); + if (userSnowballCount >= 5) { + throw new BadRequestException( + '스노우볼은 최대 5개까지 생성할 수 있습니다.' + ); + } + const snowball = this.snowballRepository.create({ - user_id: userid, - title: createSnowballDto.title, - main_decoration_color: createSnowballDto.main_decoration_color, - main_decoration_id: createSnowballDto.main_decoration_id, + user_id: user.id, + ...createSnowballDto, message_private: createSnowballDto.is_message_private ? new Date() : null }); const savedSnowball = await this.snowballRepository.save(snowball); const combinedSnowballDto: SnowballDto = { - id: savedSnowball.id, - title: savedSnowball.title, - main_decoration_color: savedSnowball.main_decoration_color, - main_decoration_id: savedSnowball.main_decoration_id, + ...savedSnowball, is_message_private: savedSnowball.message_private === null ? false : true, message_list: [] }; diff --git a/back/src/modules/user/user.module.ts b/back/src/modules/user/user.module.ts index 67b436c..b69564b 100644 --- a/back/src/modules/user/user.module.ts +++ b/back/src/modules/user/user.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { Module, forwardRef } from '@nestjs/common'; import { UserService } from './user.service'; import { UserController } from './user.controller'; import { UserEntity } from './entity/user.entity'; @@ -13,9 +13,10 @@ import { MessageService } from '../message/message.service'; @Module({ imports: [ TypeOrmModule.forFeature([UserEntity, SnowballEntity, MessageEntity]), - SnowballModule + forwardRef(() => SnowballModule) ], controllers: [UserController], - providers: [UserService, JWTGuard, SnowballService, MessageService] + providers: [UserService, JWTGuard, SnowballService, MessageService], + exports: [UserService] }) export class UserModule {} diff --git a/back/src/modules/user/user.service.ts b/back/src/modules/user/user.service.ts index ca66513..af2c5a8 100644 --- a/back/src/modules/user/user.service.ts +++ b/back/src/modules/user/user.service.ts @@ -1,4 +1,9 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; +import { + Inject, + Injectable, + NotFoundException, + forwardRef +} from '@nestjs/common'; import { UserEntity } from './entity/user.entity'; import { Repository } from 'typeorm'; import { InjectRepository } from '@nestjs/typeorm'; @@ -16,6 +21,7 @@ interface userData { @Injectable() export class UserService { constructor( + @Inject(forwardRef(() => SnowballService)) private readonly snowballService: SnowballService, @InjectRepository(UserEntity) private readonly userRepository: Repository From 79ff4330f91ade24a2d4489a69d08f16dcc560a5 Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 30 Nov 2023 14:31:02 +0900 Subject: [PATCH 148/185] =?UTF-8?q?Revert=20"feat:=20=EC=8A=A4=EB=85=B8?= =?UTF-8?q?=EC=9A=B0=EB=B3=BC=20=EC=84=9C=EB=B9=84=EC=8A=A4=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=9C=A0=EC=A0=80=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=B4=EC=84=9C=20circular=20dependency=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit ab716ed7dd34cfc19c9ab61d39e331a0e35d40ef. --- back/src/modules/snowball/snowball.module.ts | 6 ++-- back/src/modules/snowball/snowball.service.ts | 34 +++++-------------- back/src/modules/user/user.module.ts | 7 ++-- back/src/modules/user/user.service.ts | 8 +---- 4 files changed, 15 insertions(+), 40 deletions(-) diff --git a/back/src/modules/snowball/snowball.module.ts b/back/src/modules/snowball/snowball.module.ts index 513516c..815ed7b 100644 --- a/back/src/modules/snowball/snowball.module.ts +++ b/back/src/modules/snowball/snowball.module.ts @@ -1,4 +1,4 @@ -import { Module, forwardRef } from '@nestjs/common'; +import { Module } from '@nestjs/common'; import { SnowballController } from './snowball.controller'; import { SnowballService } from './snowball.service'; import { MessageModule } from '../message/message.module'; @@ -8,13 +8,11 @@ import { JWTGuard } from '../../common/guards/jwt.guard'; import { hasJWTGuard } from 'src/common/guards/hasJwt.guard'; import { MessageEntity } from '../message/entity/message.entity'; import { MessageService } from '../message/message.service'; -import { UserModule } from '../user/user.module'; @Module({ imports: [ TypeOrmModule.forFeature([SnowballEntity, MessageEntity]), - MessageModule, - forwardRef(() => UserModule) + MessageModule ], controllers: [SnowballController], providers: [SnowballService, MessageService, JWTGuard, hasJWTGuard], diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index aea2e6f..e045a0f 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -1,10 +1,4 @@ -import { - BadRequestException, - Inject, - Injectable, - NotFoundException, - forwardRef -} from '@nestjs/common'; +import { Injectable, NotFoundException } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { SnowballEntity } from './entity/snowball.entity'; @@ -15,7 +9,6 @@ import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; import { UpdateMainDecoDto } from './dto/update-main-decoration.dto'; import { UserDto } from '../user/dto/user.dto'; import { MessageService } from '../message/message.service'; -import { UserService } from '../user/user.service'; export interface SnowballInfo { snowball_count: number; @@ -28,8 +21,6 @@ export interface SnowballInfo { export class SnowballService { constructor( private readonly messageService: MessageService, - @Inject(forwardRef(() => UserService)) - private readonly userService: UserService, @InjectRepository(SnowballEntity) private readonly snowballRepository: Repository ) {} @@ -38,27 +29,20 @@ export class SnowballService { userid: number, createSnowballDto: ReqCreateSnowballDto ): Promise { - // 유저있는지 확인 - const user = await this.userService.getUserData(userid.toString()); - // create a new snowball if user has less than 5 snowballs - const userSnowballCount = await this.snowballRepository.count({ - where: { user_id: user.id } - }); - if (userSnowballCount >= 5) { - throw new BadRequestException( - '스노우볼은 최대 5개까지 생성할 수 있습니다.' - ); - } - const snowball = this.snowballRepository.create({ - user_id: user.id, - ...createSnowballDto, + user_id: userid, + title: createSnowballDto.title, + main_decoration_color: createSnowballDto.main_decoration_color, + main_decoration_id: createSnowballDto.main_decoration_id, message_private: createSnowballDto.is_message_private ? new Date() : null }); const savedSnowball = await this.snowballRepository.save(snowball); const combinedSnowballDto: SnowballDto = { - ...savedSnowball, + id: savedSnowball.id, + title: savedSnowball.title, + main_decoration_color: savedSnowball.main_decoration_color, + main_decoration_id: savedSnowball.main_decoration_id, is_message_private: savedSnowball.message_private === null ? false : true, message_list: [] }; diff --git a/back/src/modules/user/user.module.ts b/back/src/modules/user/user.module.ts index b69564b..67b436c 100644 --- a/back/src/modules/user/user.module.ts +++ b/back/src/modules/user/user.module.ts @@ -1,4 +1,4 @@ -import { Module, forwardRef } from '@nestjs/common'; +import { Module } from '@nestjs/common'; import { UserService } from './user.service'; import { UserController } from './user.controller'; import { UserEntity } from './entity/user.entity'; @@ -13,10 +13,9 @@ import { MessageService } from '../message/message.service'; @Module({ imports: [ TypeOrmModule.forFeature([UserEntity, SnowballEntity, MessageEntity]), - forwardRef(() => SnowballModule) + SnowballModule ], controllers: [UserController], - providers: [UserService, JWTGuard, SnowballService, MessageService], - exports: [UserService] + providers: [UserService, JWTGuard, SnowballService, MessageService] }) export class UserModule {} diff --git a/back/src/modules/user/user.service.ts b/back/src/modules/user/user.service.ts index af2c5a8..ca66513 100644 --- a/back/src/modules/user/user.service.ts +++ b/back/src/modules/user/user.service.ts @@ -1,9 +1,4 @@ -import { - Inject, - Injectable, - NotFoundException, - forwardRef -} from '@nestjs/common'; +import { Injectable, NotFoundException } from '@nestjs/common'; import { UserEntity } from './entity/user.entity'; import { Repository } from 'typeorm'; import { InjectRepository } from '@nestjs/typeorm'; @@ -21,7 +16,6 @@ interface userData { @Injectable() export class UserService { constructor( - @Inject(forwardRef(() => SnowballService)) private readonly snowballService: SnowballService, @InjectRepository(UserEntity) private readonly userRepository: Repository From 53fbb00b7948deae2876e5c45d3264140937b3c7 Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 30 Nov 2023 15:22:11 +0900 Subject: [PATCH 149/185] =?UTF-8?q?feat:=20DTO=20=EB=B2=A8=EB=A6=AC?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=EC=85=98=20=EC=84=A4=EC=A0=95,=20=EB=B0=94?= =?UTF-8?q?=ED=85=80=EB=8D=B0=EC=BD=94=EB=A0=88=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=BB=AC=EB=9F=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 송현우 --- .../dto/request/req-create-snowball.dto.ts | 24 +++++++++++- .../dto/request/req-update-snowball.dto.ts | 8 +++- .../dto/response/res-update-snowball.dto.ts | 10 ++++- back/src/modules/snowball/dto/snowball.dto.ts | 21 +++++++++- .../dto/update-main-decoration.dto.ts | 21 +++++++++- .../snowball/entity/snowball.entity.ts | 6 +++ back/src/modules/snowball/snowball.service.ts | 39 +++++++++++++------ 7 files changed, 113 insertions(+), 16 deletions(-) diff --git a/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts b/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts index 512c6cd..cbf1b48 100644 --- a/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts +++ b/back/src/modules/snowball/dto/request/req-create-snowball.dto.ts @@ -3,18 +3,22 @@ import { IsNotEmpty, IsBoolean, IsNumber, - IsHexColor + IsHexColor, + Min, + Length } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class ReqCreateSnowballDto { @IsString() @IsNotEmpty() + @Length(1, 10) @ApiProperty({ type: String, description: '스노우볼 제목' }) readonly title: string; @IsNumber() @IsNotEmpty() + @Min(1) @ApiProperty({ type: Number, description: '장식 id' }) readonly main_decoration_id: number; @@ -23,6 +27,24 @@ export class ReqCreateSnowballDto { @ApiProperty({ type: String, description: '장식 색상', example: '#FFFFFF' }) readonly main_decoration_color: string; + @IsNumber() + @IsNotEmpty() + @Min(1) + @ApiProperty({ + type: Number, + description: '스노우볼 하단 장식 데코레이션 id' + }) + readonly bottom_decoration_id: number; + + @IsHexColor() + @IsNotEmpty() + @ApiProperty({ + type: String, + description: '스노우볼 하단 장식 색상', + example: '#FFFFFF' + }) + readonly bottom_decoration_color: string; + @IsBoolean() @IsNotEmpty() @ApiProperty({ diff --git a/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts b/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts index a58c058..fc92f85 100644 --- a/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/request/req-update-snowball.dto.ts @@ -1,9 +1,15 @@ -import { IsString, IsNotEmpty, IsBoolean } from '@nestjs/class-validator'; +import { + IsString, + IsNotEmpty, + IsBoolean, + Length +} from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class ReqUpdateSnowballDto { @IsString() @IsNotEmpty() + @Length(1, 10) @ApiProperty({ type: String, description: '스노우볼 제목' }) readonly title: string; diff --git a/back/src/modules/snowball/dto/response/res-update-snowball.dto.ts b/back/src/modules/snowball/dto/response/res-update-snowball.dto.ts index b60be81..3a0942b 100644 --- a/back/src/modules/snowball/dto/response/res-update-snowball.dto.ts +++ b/back/src/modules/snowball/dto/response/res-update-snowball.dto.ts @@ -1,12 +1,20 @@ -import { IsString, IsBoolean, IsNumber } from '@nestjs/class-validator'; +import { + IsString, + IsBoolean, + IsNumber, + Min, + Length +} from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class ResUpdateSnowballDto { @IsNumber() + @Min(1) @ApiProperty({ type: Number, description: '스노우볼 id' }) readonly snowball_id: number; @IsString() + @Length(1, 10) @ApiProperty({ type: String, description: '변경된 스노우볼 제목' }) readonly title: string; diff --git a/back/src/modules/snowball/dto/snowball.dto.ts b/back/src/modules/snowball/dto/snowball.dto.ts index 47a3ada..621156c 100644 --- a/back/src/modules/snowball/dto/snowball.dto.ts +++ b/back/src/modules/snowball/dto/snowball.dto.ts @@ -4,7 +4,9 @@ import { IsNumber, IsNotEmpty, ValidateNested, - IsHexColor + IsHexColor, + Length, + Min } from '@nestjs/class-validator'; import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; @@ -13,11 +15,13 @@ import { MessageDto } from '../../message/dto/message.dto'; export class SnowballDto { @IsString() @IsNotEmpty() + @Length(1, 10) @ApiProperty({ type: String, description: '스노우볼 제목' }) readonly title: string; @IsNotEmpty() @IsNumber() + @Min(1) @ApiProperty({ type: Number, description: '스노우볼 id' }) readonly id: number; @@ -31,6 +35,7 @@ export class SnowballDto { @IsNumber() @IsNotEmpty() + @Min(1) @ApiProperty({ type: Number, description: '스노우볼 메인 장식 데코레이션 id' @@ -42,6 +47,20 @@ export class SnowballDto { @ApiProperty({ type: String, description: '스노우볼 메인 장식 색상' }) readonly main_decoration_color: string; + @IsNumber() + @IsNotEmpty() + @Min(1) + @ApiProperty({ + type: Number, + description: '스노우볼 하단 장식 데코레이션 id' + }) + readonly bottom_decoration_id: number; + + @IsHexColor() + @IsNotEmpty() + @ApiProperty({ type: String, description: '스노우볼 하단 장식 색상' }) + readonly bottom_decoration_color: string; + @ValidateNested({ each: true }) @Type(() => MessageDto) @ApiProperty({ diff --git a/back/src/modules/snowball/dto/update-main-decoration.dto.ts b/back/src/modules/snowball/dto/update-main-decoration.dto.ts index 2882b6a..afc1952 100644 --- a/back/src/modules/snowball/dto/update-main-decoration.dto.ts +++ b/back/src/modules/snowball/dto/update-main-decoration.dto.ts @@ -1,8 +1,9 @@ import { ApiProperty } from '@nestjs/swagger'; -import { IsNumber, IsNotEmpty, IsHexColor } from 'class-validator'; +import { IsNumber, IsNotEmpty, IsHexColor, Min } from 'class-validator'; export class UpdateMainDecoDto { @IsNumber() + @Min(1) @IsNotEmpty() @ApiProperty({ type: Number, description: '장식 id' }) readonly main_decoration_id: number; @@ -11,4 +12,22 @@ export class UpdateMainDecoDto { @IsNotEmpty() @ApiProperty({ type: String, description: '장식 색상', example: '#FFFFFF' }) readonly main_decoration_color: string; + + @IsNumber() + @IsNotEmpty() + @Min(1) + @ApiProperty({ + type: Number, + description: '스노우볼 하단 장식 데코레이션 id' + }) + readonly bottom_decoration_id: number; + + @IsHexColor() + @IsNotEmpty() + @ApiProperty({ + type: String, + description: '스노우볼 하단 장식 색상', + example: '#FFFFFF' + }) + readonly bottom_decoration_color: string; } diff --git a/back/src/modules/snowball/entity/snowball.entity.ts b/back/src/modules/snowball/entity/snowball.entity.ts index af8c7c6..f780bc7 100644 --- a/back/src/modules/snowball/entity/snowball.entity.ts +++ b/back/src/modules/snowball/entity/snowball.entity.ts @@ -30,6 +30,12 @@ export class SnowballEntity { @Column({ type: 'char', length: 7 }) main_decoration_color: string; + @Column() + bottom_decoration_id: number; + + @Column() + bottom_decoration_color: string; + @CreateDateColumn({ nullable: true, default: null }) message_private: Date | null; diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index e045a0f..671892f 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -1,4 +1,8 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; +import { + BadRequestException, + Injectable, + NotFoundException +} from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { SnowballEntity } from './entity/snowball.entity'; @@ -9,7 +13,6 @@ import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; import { UpdateMainDecoDto } from './dto/update-main-decoration.dto'; import { UserDto } from '../user/dto/user.dto'; import { MessageService } from '../message/message.service'; - export interface SnowballInfo { snowball_count: number; message_count: number; @@ -29,20 +32,25 @@ export class SnowballService { userid: number, createSnowballDto: ReqCreateSnowballDto ): Promise { + // create a new snowball if user has less than 5 snowballs + const userSnowballCount = await this.snowballRepository.count({ + where: { user_id: userid } + }); + if (userSnowballCount >= 5) { + throw new BadRequestException( + '스노우볼은 최대 5개까지 생성할 수 있습니다.' + ); + } + const snowball = this.snowballRepository.create({ user_id: userid, - title: createSnowballDto.title, - main_decoration_color: createSnowballDto.main_decoration_color, - main_decoration_id: createSnowballDto.main_decoration_id, + ...createSnowballDto, message_private: createSnowballDto.is_message_private ? new Date() : null }); const savedSnowball = await this.snowballRepository.save(snowball); const combinedSnowballDto: SnowballDto = { - id: savedSnowball.id, - title: savedSnowball.title, - main_decoration_color: savedSnowball.main_decoration_color, - main_decoration_id: savedSnowball.main_decoration_id, + ...savedSnowball, is_message_private: savedSnowball.message_private === null ? false : true, message_list: [] }; @@ -96,6 +104,8 @@ export class SnowballService { title: snowball.title, main_decoration_id: snowball.main_decoration_id, main_decoration_color: snowball.main_decoration_color, + bottom_decoration_id: snowball.bottom_decoration_id, + bottom_decoration_color: snowball.bottom_decoration_color, is_message_private: is_message_private, message_list: await this.messageService.getMessageList( snowball.id, @@ -110,14 +120,21 @@ export class SnowballService { updateMainDecoDto: UpdateMainDecoDto, snowball_id: number ): Promise { - const { main_decoration_id, main_decoration_color } = updateMainDecoDto; + const { + main_decoration_id, + main_decoration_color, + bottom_decoration_id, + bottom_decoration_color + } = updateMainDecoDto; const updateResult = await this.snowballRepository .createQueryBuilder() .update(SnowballEntity) .set({ main_decoration_id: main_decoration_id, - main_decoration_color: main_decoration_color + main_decoration_color: main_decoration_color, + bottom_decoration_id: bottom_decoration_id, + bottom_decoration_color: bottom_decoration_color }) .where('id = :id', { id: snowball_id }) .execute(); From bf93920c9d97b35d29024a00d0869114be8b7388 Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 30 Nov 2023 15:37:02 +0900 Subject: [PATCH 150/185] =?UTF-8?q?feat:=20letterid=20=EB=A7=A5=EC=8A=A4?= =?UTF-8?q?=203=EC=9C=BC=EB=A1=9C=20=EC=A0=9C=ED=95=9C=ED=95=9C=EA=B1=B0?= =?UTF-8?q?=20=ED=92=80=EC=96=B4=EC=A4=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/modules/message/dto/request/req-create-message.dto.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/back/src/modules/message/dto/request/req-create-message.dto.ts b/back/src/modules/message/dto/request/req-create-message.dto.ts index ecf66a4..221cd2c 100644 --- a/back/src/modules/message/dto/request/req-create-message.dto.ts +++ b/back/src/modules/message/dto/request/req-create-message.dto.ts @@ -4,8 +4,7 @@ import { IsNumber, IsHexColor, Length, - Min, - Max + Min } from '@nestjs/class-validator'; import { ApiProperty } from '@nestjs/swagger'; @@ -36,7 +35,6 @@ export class ReqCreateMessageDto { @IsNumber() @Min(1) - @Max(3) @IsNotEmpty() @ApiProperty({ type: Number, description: '편지지 종류', example: 1 }) readonly letter_id: number; From 3b24049a442265c517dd1245f46354a1027697e8 Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 30 Nov 2023 15:40:46 +0900 Subject: [PATCH 151/185] =?UTF-8?q?feat:=20letterid=20=EB=A7=A5=EC=8A=A4?= =?UTF-8?q?=203=EC=9C=BC=EB=A1=9C=20=EC=A0=9C=ED=95=9C=ED=95=9C=EA=B1=B0?= =?UTF-8?q?=20=ED=92=80=EC=96=B4=EC=A4=8C=20message.dto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/message/dto/message.dto.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/back/src/modules/message/dto/message.dto.ts b/back/src/modules/message/dto/message.dto.ts index 7a240ac..91d2866 100644 --- a/back/src/modules/message/dto/message.dto.ts +++ b/back/src/modules/message/dto/message.dto.ts @@ -25,7 +25,6 @@ export class MessageDto { @IsNumber() @Min(1) - @Max(3) @ApiProperty({ type: Number, description: '편지지 종류' }) readonly letter_id: number; From 99fef0ff36b8d27e07fb4a512b1abdd16730a7d8 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Thu, 30 Nov 2023 16:37:30 +0900 Subject: [PATCH 152/185] =?UTF-8?q?fix:=20=EB=B0=A9=EB=AC=B8=EC=9E=90=20pr?= =?UTF-8?q?ivate=20=EB=A6=AC=ED=84=B4=EA=B0=92=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../message/dto/private-message.dto.ts | 31 +++++++++++++++++++ back/src/modules/message/message.service.ts | 14 ++++++--- back/src/modules/snowball/dto/snowball.dto.ts | 8 ++--- 3 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 back/src/modules/message/dto/private-message.dto.ts diff --git a/back/src/modules/message/dto/private-message.dto.ts b/back/src/modules/message/dto/private-message.dto.ts new file mode 100644 index 0000000..7ec3abf --- /dev/null +++ b/back/src/modules/message/dto/private-message.dto.ts @@ -0,0 +1,31 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsNumber, IsDate, IsHexColor, Min, Max } from 'class-validator'; + +export class PrivateMessageDto { + @IsNumber() + @ApiProperty({ type: Number, description: '메시지 ID' }) + readonly id: number; + + @IsNumber() + @Min(1) + @ApiProperty({ type: Number, description: '장식 id' }) + readonly decoration_id: number; + + @IsHexColor() + @ApiProperty({ type: String, description: '장식 색상' }) + readonly decoration_color: string; + + @IsDate() + @ApiProperty({ type: Date, description: '열린 날짜' }) + readonly opened: Date | null; + + @IsDate() + @ApiProperty({ type: Date, description: '생성 날짜' }) + readonly created: Date; + + @IsNumber() + @Min(1) + @Max(72) + @ApiProperty({ type: Number, description: '메세지 위치' }) + readonly location: number; +} diff --git a/back/src/modules/message/message.service.ts b/back/src/modules/message/message.service.ts index 2844ae1..f2a2efe 100644 --- a/back/src/modules/message/message.service.ts +++ b/back/src/modules/message/message.service.ts @@ -15,6 +15,7 @@ import { MessageDto } from './dto/message.dto'; import { plainToClass } from '@nestjs/class-transformer'; import { UpdateMessageDecorationDto } from './dto/update-message-decoration.dto'; import { UpdateMessageLocationDto } from './dto/update-message-location.dto'; +import { PrivateMessageDto } from './dto/private-message.dto'; @Injectable() export class MessageService { @@ -176,7 +177,7 @@ export class MessageService { async getMessageList( snowball_id: number, is_private_contents: boolean - ): Promise { + ): Promise { const messages = await this.messageRepository.find({ where: { snowball_id: snowball_id, is_deleted: false }, select: [ @@ -192,13 +193,16 @@ export class MessageService { ] }); if (is_private_contents) { - messages.map(message => { - message.content = '비공개 메세지'; - message.sender = '비공개 발신자'; + const privateMessages = messages.map(message => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { letter_id, content, sender, ...rest } = message; + return rest; }); + return plainToClass(PrivateMessageDto, privateMessages); } - return messages; + return plainToClass(MessageDto, messages); } + async findLocation(user_id: number): Promise { const findLocations = this.messageRepository .createQueryBuilder('message') diff --git a/back/src/modules/snowball/dto/snowball.dto.ts b/back/src/modules/snowball/dto/snowball.dto.ts index 621156c..3f78dca 100644 --- a/back/src/modules/snowball/dto/snowball.dto.ts +++ b/back/src/modules/snowball/dto/snowball.dto.ts @@ -8,9 +8,10 @@ import { Length, Min } from '@nestjs/class-validator'; -import { Type } from '@nestjs/class-transformer'; +//import { Type } from '@nestjs/class-transformer'; import { ApiProperty } from '@nestjs/swagger'; import { MessageDto } from '../../message/dto/message.dto'; +import { PrivateMessageDto } from 'src/modules/message/dto/private-message.dto'; export class SnowballDto { @IsString() @@ -62,10 +63,9 @@ export class SnowballDto { readonly bottom_decoration_color: string; @ValidateNested({ each: true }) - @Type(() => MessageDto) @ApiProperty({ - type: [MessageDto], + type: [MessageDto, PrivateMessageDto], description: '스노우볼 속 메시지 리스트' }) - readonly message_list: MessageDto[]; + readonly message_list: MessageDto[] | PrivateMessageDto[]; } From 91558217a7f9bbd4b2cd57ef9d2ea19a31268971 Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 30 Nov 2023 16:40:51 +0900 Subject: [PATCH 153/185] =?UTF-8?q?feat:=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8=20=EC=8A=A4=EB=85=B8=EC=9A=B0=EB=B3=BC=EC=8B=9C=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=EA=B0=80=20=EC=8A=A4=EB=85=B8=EC=9A=B0?= =?UTF-8?q?=EB=B3=BC=20=EC=A3=BC=EC=9D=B8=EC=9D=B8=EC=A7=80=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/modules/snowball/snowball.controller.ts | 4 +++- back/src/modules/snowball/snowball.service.ts | 17 ++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index 88ff4eb..b88c52c 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -75,11 +75,13 @@ export class SnowballController { @ApiBody({ type: ReqUpdateSnowballDto }) updateSnowball( @Param('snowball_id') snowball_id: number, + @Req() req: JWTRequest, @Body() updateSnowballDto: ReqUpdateSnowballDto ) { const snowball = this.snowballService.updateSnowball( updateSnowballDto, - snowball_id + snowball_id, + req.user.id ); return snowball; } diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 671892f..4dd2bc3 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -13,6 +13,7 @@ import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; import { UpdateMainDecoDto } from './dto/update-main-decoration.dto'; import { UserDto } from '../user/dto/user.dto'; import { MessageService } from '../message/message.service'; + export interface SnowballInfo { snowball_count: number; message_count: number; @@ -32,7 +33,7 @@ export class SnowballService { userid: number, createSnowballDto: ReqCreateSnowballDto ): Promise { - // create a new snowball if user has less than 5 snowballs + // 유저가 스노우볼을 5개 이상 생성할 수 없다. const userSnowballCount = await this.snowballRepository.count({ where: { user_id: userid } }); @@ -59,10 +60,19 @@ export class SnowballService { async updateSnowball( updateSnowballDto: ReqUpdateSnowballDto, - snowball_id: number + snowball_id: number, + user_pk: number ): Promise { const { title, is_message_private } = updateSnowballDto; + //스노우볼 존재 여부 exception 나눠주기 위해 쿼리문 추가 + const snowball = await this.snowballRepository.count({ + where: { id: snowball_id } + }); + if (!snowball) { + throw new NotFoundException('업데이트할 스노우볼이 존재하지 않습니다.'); + } + const updateResult = await this.snowballRepository .createQueryBuilder() .update(SnowballEntity) @@ -71,9 +81,10 @@ export class SnowballService { message_private: is_message_private ? new Date() : null }) .where('id = :id', { id: snowball_id }) + .andWhere('user_id = :user_id', { user_id: user_pk }) .execute(); if (!updateResult.affected) { - throw new NotFoundException('업데이트할 스노우볼이 존재하지 않습니다.'); + throw new NotFoundException('스노우볼 업데이트 권한이 없습니다'); } // Return the updated snowball From f745c06eb55f0a17b5760516044a6b648d1fcec7 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Thu, 30 Nov 2023 17:00:24 +0900 Subject: [PATCH 154/185] =?UTF-8?q?fix:=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EB=B2=84=20strategy=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/common/strategy/kakao-auth.strategy.ts | 2 +- back/src/common/strategy/naver-auth.strategy.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/back/src/common/strategy/kakao-auth.strategy.ts b/back/src/common/strategy/kakao-auth.strategy.ts index 26b5ce5..f3e827d 100644 --- a/back/src/common/strategy/kakao-auth.strategy.ts +++ b/back/src/common/strategy/kakao-auth.strategy.ts @@ -23,7 +23,7 @@ export class KakaoAuthStrategy extends PassportStrategy(Strategy, 'kakao') { try { console.log(profile); const user = { - id: profile.id, + user_id: profile.id, name: profile.displayName, provider: profile.provider, accessToken, diff --git a/back/src/common/strategy/naver-auth.strategy.ts b/back/src/common/strategy/naver-auth.strategy.ts index 909b48a..5e7de72 100644 --- a/back/src/common/strategy/naver-auth.strategy.ts +++ b/back/src/common/strategy/naver-auth.strategy.ts @@ -23,7 +23,7 @@ export class NaverAuthStrategy extends PassportStrategy(Strategy, 'naver') { try { console.log(profile); const user = { - id: profile.id, + user_id: profile.id, name: profile.name, provider: profile.provider, accessToken, From 50e114370fcedbd5857944c79bd07e80e5316c33 Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 30 Nov 2023 17:17:18 +0900 Subject: [PATCH 155/185] =?UTF-8?q?feat:=20jwtRequest=20=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=EC=85=89=ED=84=B0=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit jwtRequestInterceptor 에서 토큰 왔나 안왔나 체크하고 왔으면 req.hasToken true 해주고 req.user에jwt토큰에 있는 정보 담아줌 --- back/src/common/guards/hasJwt.guard.ts | 25 ------------- .../interceptors/jwtRequest.interceptor.ts | 35 +++++++++++++++++++ .../src/common/interface/request.interface.ts | 4 +-- .../modules/snowball/snowball.controller.ts | 14 ++++---- back/src/modules/snowball/snowball.module.ts | 3 +- back/src/modules/snowball/snowball.service.ts | 25 +++++++------ 6 files changed, 55 insertions(+), 51 deletions(-) delete mode 100644 back/src/common/guards/hasJwt.guard.ts create mode 100644 back/src/common/interceptors/jwtRequest.interceptor.ts diff --git a/back/src/common/guards/hasJwt.guard.ts b/back/src/common/guards/hasJwt.guard.ts deleted file mode 100644 index a28c290..0000000 --- a/back/src/common/guards/hasJwt.guard.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { CanActivate, ExecutionContext, Injectable, Req } from '@nestjs/common'; -import { Request } from 'express'; - -@Injectable() -export class hasJWTGuard implements CanActivate { - constructor() {} - - async canActivate(context: ExecutionContext): Promise { - const request = context.switchToHttp().getRequest(); - const token = this.extractTokenFromHeader(request); - if (!token) { - request['hasToken'] = false; - } else { - request['hasToken'] = true; - } - return true; - } - - private extractTokenFromHeader(@Req() req: Request): string | undefined { - const [type, token] = req.headers.authorization?.split(' ') ?? []; - return type === 'Bearer' ? token : undefined; - } -} - -// 커스텀데코레이터, class-trasformer로 변경 diff --git a/back/src/common/interceptors/jwtRequest.interceptor.ts b/back/src/common/interceptors/jwtRequest.interceptor.ts new file mode 100644 index 0000000..2bd940e --- /dev/null +++ b/back/src/common/interceptors/jwtRequest.interceptor.ts @@ -0,0 +1,35 @@ +import { + Injectable, + NestInterceptor, + ExecutionContext, + CallHandler +} from '@nestjs/common'; +import { Observable } from 'rxjs'; +import { JwtService } from '@nestjs/jwt'; + +@Injectable() +export class JWTToRequestInterceptor implements NestInterceptor { + constructor(private readonly jwtService: JwtService) {} + + async intercept( + context: ExecutionContext, + next: CallHandler + ): Promise> { + console.log('Before...'); + + const request = context.switchToHttp().getRequest(); + const [type, token] = request.headers.authorization?.split(' ') ?? []; + if (type === 'Bearer' && token) { + request['hasToken'] = true; + const payload = await this.jwtService.verify(token, { + secret: process.env.JWT_ACCESS_SECRET + }); + + request['user'] = payload; + } else { + request['hasToken'] = false; + } + + return next.handle(); + } +} diff --git a/back/src/common/interface/request.interface.ts b/back/src/common/interface/request.interface.ts index 8a9a1a6..92a44a2 100644 --- a/back/src/common/interface/request.interface.ts +++ b/back/src/common/interface/request.interface.ts @@ -6,8 +6,6 @@ export interface JWTRequest extends Request { name: string; user_id: string; }; -} -export interface hasTokenRequest extends Request { - hasToken: boolean; + hasToken?: boolean; } diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index b88c52c..b921057 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -7,7 +7,8 @@ import { Get, HttpCode, UseGuards, - Req + Req, + UseInterceptors } from '@nestjs/common'; import { SnowballService } from './snowball.service'; import { @@ -23,12 +24,9 @@ import { ReqUpdateSnowballDto } from './dto/request/req-update-snowball.dto'; import { SnowballDto } from './dto/snowball.dto'; import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; import { JWTGuard } from 'src/common/guards/jwt.guard'; -import { hasJWTGuard } from 'src/common/guards/hasJwt.guard'; import { UpdateMainDecoDto } from './dto/update-main-decoration.dto'; -import { - JWTRequest, - hasTokenRequest -} from '../../common/interface/request.interface'; +import { JWTRequest } from '../../common/interface/request.interface'; +import { JWTToRequestInterceptor } from 'src/common/interceptors/JwtRequest.interceptor'; @ApiTags('Snowball API') @Controller('snowball') @@ -87,7 +85,7 @@ export class SnowballController { } @Get('/:snowball_id') - @UseGuards(hasJWTGuard) + @UseInterceptors(JWTToRequestInterceptor) @ApiBearerAuth('jwt-token') @HttpCode(200) @ApiResponse({ @@ -100,7 +98,7 @@ export class SnowballController { description: '스노우볼의 정보를 조회합니다.' }) async getSnowball( - @Req() req: hasTokenRequest, + @Req() req: JWTRequest, @Param('snowball_id') snowball_id: number ) { const snowball = await this.snowballService.getSnowball( diff --git a/back/src/modules/snowball/snowball.module.ts b/back/src/modules/snowball/snowball.module.ts index 815ed7b..4cb175c 100644 --- a/back/src/modules/snowball/snowball.module.ts +++ b/back/src/modules/snowball/snowball.module.ts @@ -5,7 +5,6 @@ import { MessageModule } from '../message/message.module'; import { TypeOrmModule } from '@nestjs/typeorm'; import { SnowballEntity } from './entity/snowball.entity'; import { JWTGuard } from '../../common/guards/jwt.guard'; -import { hasJWTGuard } from 'src/common/guards/hasJwt.guard'; import { MessageEntity } from '../message/entity/message.entity'; import { MessageService } from '../message/message.service'; @@ -15,7 +14,7 @@ import { MessageService } from '../message/message.service'; MessageModule ], controllers: [SnowballController], - providers: [SnowballService, MessageService, JWTGuard, hasJWTGuard], + providers: [SnowballService, MessageService, JWTGuard], exports: [SnowballService, MessageService, TypeOrmModule] }) export class SnowballModule {} diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 4dd2bc3..9b86546 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -58,6 +58,16 @@ export class SnowballService { return combinedSnowballDto; } + async doesSnowballExist(snowball_id: number): Promise { + const snowball = await this.snowballRepository.count({ + where: { id: snowball_id } + }); + if (!snowball) { + throw new NotFoundException('업데이트할 스노우볼이 존재하지 않습니다.'); + } + return true; + } + async updateSnowball( updateSnowballDto: ReqUpdateSnowballDto, snowball_id: number, @@ -65,13 +75,7 @@ export class SnowballService { ): Promise { const { title, is_message_private } = updateSnowballDto; - //스노우볼 존재 여부 exception 나눠주기 위해 쿼리문 추가 - const snowball = await this.snowballRepository.count({ - where: { id: snowball_id } - }); - if (!snowball) { - throw new NotFoundException('업데이트할 스노우볼이 존재하지 않습니다.'); - } + await this.doesSnowballExist(snowball_id); const updateResult = await this.snowballRepository .createQueryBuilder() @@ -111,12 +115,7 @@ export class SnowballService { const is_private_contents = !hasToken && is_message_private; const resSnowball: SnowballDto = { - id: snowball.id, - title: snowball.title, - main_decoration_id: snowball.main_decoration_id, - main_decoration_color: snowball.main_decoration_color, - bottom_decoration_id: snowball.bottom_decoration_id, - bottom_decoration_color: snowball.bottom_decoration_color, + ...snowball, is_message_private: is_message_private, message_list: await this.messageService.getMessageList( snowball.id, From 5cfc864985eacd158eafacb2d7b2579465c10cb0 Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 30 Nov 2023 17:46:00 +0900 Subject: [PATCH 156/185] =?UTF-8?q?feat:=20=EB=A9=94=EC=9D=B8=EB=8D=B0?= =?UTF-8?q?=EC=BD=94=EB=A0=88=EC=9D=B4=EC=85=98/=EB=B0=94=ED=85=80?= =?UTF-8?q?=EB=8D=B0=EC=BD=94=EB=A0=88=EC=9D=B4=EC=85=98=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20=ED=95=A0=EB=95=8C=20=EC=9C=A0=EC=A0=80=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/snowball/snowball.controller.ts | 6 ++-- back/src/modules/snowball/snowball.service.ts | 32 ++++++++++++------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index b921057..a7cc020 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -123,11 +123,13 @@ export class SnowballController { @ApiBody({ type: UpdateMainDecoDto }) async updateMainDecoration( @Param('snowball_id') snowball_id: number, - @Body() updateMainDecoDto: UpdateMainDecoDto + @Body() updateMainDecoDto: UpdateMainDecoDto, + @Req() req: JWTRequest ) { const snowball = await this.snowballService.updateMainDecoration( updateMainDecoDto, - snowball_id + snowball_id, + req.user.id ); return snowball; } diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index 9b86546..f853af6 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -126,30 +126,38 @@ export class SnowballService { return resSnowball; } + async doesDecorationExist(decoration_id: number): Promise { + const decoration = await this.snowballRepository.count({ + where: { id: decoration_id } + }); + if (!decoration) { + throw new NotFoundException('업데이트할 장식이 존재하지 않습니다.'); + } + return true; + } + async updateMainDecoration( updateMainDecoDto: UpdateMainDecoDto, - snowball_id: number + snowball_id: number, + user_pk: number ): Promise { - const { - main_decoration_id, - main_decoration_color, - bottom_decoration_id, - bottom_decoration_color - } = updateMainDecoDto; + await this.doesSnowballExist(snowball_id); + //포렌키 설정하면 이거 안해줘도 될거 같긴함 + await this.doesDecorationExist(updateMainDecoDto.main_decoration_id); + await this.doesDecorationExist(updateMainDecoDto.bottom_decoration_id); const updateResult = await this.snowballRepository .createQueryBuilder() .update(SnowballEntity) .set({ - main_decoration_id: main_decoration_id, - main_decoration_color: main_decoration_color, - bottom_decoration_id: bottom_decoration_id, - bottom_decoration_color: bottom_decoration_color + ...updateMainDecoDto }) .where('id = :id', { id: snowball_id }) + .andWhere('user_id = :user_id', { user_id: user_pk }) .execute(); + if (!updateResult.affected) { - throw new NotFoundException('업데이트할 스노우볼이 존재하지 않습니다.'); + throw new NotFoundException('스노우볼을 업데이트할 권한이 없습니다.'); } return updateMainDecoDto; From 463fdd1fd7732c36d496cbbf034c4963485ff0c5 Mon Sep 17 00:00:00 2001 From: peageon Date: Thu, 30 Nov 2023 18:41:55 +0900 Subject: [PATCH 157/185] =?UTF-8?q?fix:=20JWTToRequestInterceptor=20import?= =?UTF-8?q?=20=EC=83=81=EB=8C=80=EA=B2=BD=EB=A1=9C=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/snowball/snowball.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index a7cc020..cdc454c 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -26,7 +26,7 @@ import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; import { JWTGuard } from 'src/common/guards/jwt.guard'; import { UpdateMainDecoDto } from './dto/update-main-decoration.dto'; import { JWTRequest } from '../../common/interface/request.interface'; -import { JWTToRequestInterceptor } from 'src/common/interceptors/JwtRequest.interceptor'; +import { JWTToRequestInterceptor } from '../../common/interceptors/jwtRequest.interceptor'; @ApiTags('Snowball API') @Controller('snowball') From e722b52252056f1baeac52320ce5b1ea6d7f04f1 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Thu, 30 Nov 2023 18:43:03 +0900 Subject: [PATCH 158/185] =?UTF-8?q?fix:=20auth=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4=EB=9F=AC=20api=20response=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/modules/auth/auth.controller.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/back/src/modules/auth/auth.controller.ts b/back/src/modules/auth/auth.controller.ts index 8f389d2..d9d4e40 100644 --- a/back/src/modules/auth/auth.controller.ts +++ b/back/src/modules/auth/auth.controller.ts @@ -1,7 +1,6 @@ import { Controller, Get, Req, Res, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; -import { ResInfoDto } from '../user/dto/response/res-info.dto'; import { AuthService } from './auth.service'; import { payload } from './auth.service'; @@ -29,8 +28,7 @@ export class AuthController { @UseGuards(AuthGuard('google')) @ApiResponse({ status: 200, - description: 'Google 로그인 성공 및 Info 반환', - type: ResInfoDto + description: 'Google 로그인 성공' }) @ApiResponse({ status: 401, description: 'Unauthorized' }) @ApiResponse({ @@ -72,8 +70,7 @@ export class AuthController { @UseGuards(AuthGuard('naver')) @ApiResponse({ status: 200, - description: 'Naver 로그인 성공 및 Info 반환', - type: ResInfoDto + description: 'Naver 로그인 성공' }) @ApiResponse({ status: 401, description: 'Unauthorized' }) @ApiResponse({ @@ -115,8 +112,7 @@ export class AuthController { @UseGuards(AuthGuard('kakao')) @ApiResponse({ status: 200, - description: 'Kakao 로그인 성공 및 Info 반환', - type: ResInfoDto + description: 'Kakao 로그인 성공' }) @ApiResponse({ status: 401, description: 'Unauthorized' }) @ApiResponse({ From 35edaae22910a25211716a73d2df7fb7470bba29 Mon Sep 17 00:00:00 2001 From: yunuo46 Date: Thu, 30 Nov 2023 19:03:27 +0900 Subject: [PATCH 159/185] =?UTF-8?q?fix:=20=EC=8A=A4=EB=85=B8=EC=9A=B0?= =?UTF-8?q?=EB=B3=BC=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/common/interface/request.interface.ts | 1 + .../src/modules/snowball/snowball.controller.ts | 2 +- back/src/modules/snowball/snowball.module.ts | 7 ++++++- back/src/modules/snowball/snowball.service.ts | 17 ++++++++++------- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/back/src/common/interface/request.interface.ts b/back/src/common/interface/request.interface.ts index 92a44a2..067973f 100644 --- a/back/src/common/interface/request.interface.ts +++ b/back/src/common/interface/request.interface.ts @@ -9,3 +9,4 @@ export interface JWTRequest extends Request { hasToken?: boolean; } +// 분리 diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index cdc454c..baaa7dd 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -84,9 +84,9 @@ export class SnowballController { return snowball; } + // 인터셉터 두개로 분리 @Get('/:snowball_id') @UseInterceptors(JWTToRequestInterceptor) - @ApiBearerAuth('jwt-token') @HttpCode(200) @ApiResponse({ status: 200, diff --git a/back/src/modules/snowball/snowball.module.ts b/back/src/modules/snowball/snowball.module.ts index 4cb175c..afbebe6 100644 --- a/back/src/modules/snowball/snowball.module.ts +++ b/back/src/modules/snowball/snowball.module.ts @@ -7,10 +7,15 @@ import { SnowballEntity } from './entity/snowball.entity'; import { JWTGuard } from '../../common/guards/jwt.guard'; import { MessageEntity } from '../message/entity/message.entity'; import { MessageService } from '../message/message.service'; +import { DecorationPrefixEntity } from './entity/decoration-prefix.entity'; @Module({ imports: [ - TypeOrmModule.forFeature([SnowballEntity, MessageEntity]), + TypeOrmModule.forFeature([ + SnowballEntity, + MessageEntity, + DecorationPrefixEntity + ]), MessageModule ], controllers: [SnowballController], diff --git a/back/src/modules/snowball/snowball.service.ts b/back/src/modules/snowball/snowball.service.ts index f853af6..430c9df 100644 --- a/back/src/modules/snowball/snowball.service.ts +++ b/back/src/modules/snowball/snowball.service.ts @@ -13,6 +13,7 @@ import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; import { UpdateMainDecoDto } from './dto/update-main-decoration.dto'; import { UserDto } from '../user/dto/user.dto'; import { MessageService } from '../message/message.service'; +import { DecorationPrefixEntity } from './entity/decoration-prefix.entity'; export interface SnowballInfo { snowball_count: number; @@ -26,16 +27,18 @@ export class SnowballService { constructor( private readonly messageService: MessageService, @InjectRepository(SnowballEntity) - private readonly snowballRepository: Repository + private readonly snowballRepository: Repository, + @InjectRepository(DecorationPrefixEntity) + private readonly snowballDecoRepository: Repository ) {} async createSnowball( - userid: number, + user_id: number, createSnowballDto: ReqCreateSnowballDto ): Promise { // 유저가 스노우볼을 5개 이상 생성할 수 없다. const userSnowballCount = await this.snowballRepository.count({ - where: { user_id: userid } + where: { user_id: user_id } }); if (userSnowballCount >= 5) { throw new BadRequestException( @@ -44,7 +47,7 @@ export class SnowballService { } const snowball = this.snowballRepository.create({ - user_id: userid, + user_id: user_id, ...createSnowballDto, message_private: createSnowballDto.is_message_private ? new Date() : null }); @@ -58,8 +61,9 @@ export class SnowballService { return combinedSnowballDto; } + // To Do: 조회 성능 테스트 필요 async doesSnowballExist(snowball_id: number): Promise { - const snowball = await this.snowballRepository.count({ + const snowball = await this.snowballRepository.findOne({ where: { id: snowball_id } }); if (!snowball) { @@ -127,7 +131,7 @@ export class SnowballService { } async doesDecorationExist(decoration_id: number): Promise { - const decoration = await this.snowballRepository.count({ + const decoration = await this.snowballDecoRepository.findOne({ where: { id: decoration_id } }); if (!decoration) { @@ -142,7 +146,6 @@ export class SnowballService { user_pk: number ): Promise { await this.doesSnowballExist(snowball_id); - //포렌키 설정하면 이거 안해줘도 될거 같긴함 await this.doesDecorationExist(updateMainDecoDto.main_decoration_id); await this.doesDecorationExist(updateMainDecoDto.bottom_decoration_id); From 219ce3528a057270b7361cd1bd9c94e6f5ab8e34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Fri, 1 Dec 2023 00:32:32 +0900 Subject: [PATCH 160/185] =?UTF-8?q?feat:=20cookie=EA=B8=B0=EB=B0=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/common/guards/jwt.guard.ts | 25 +++++++++++++++---- back/src/common/util/swagger.ts | 11 +------- .../src/modules/message/message.controller.ts | 14 +++++------ .../modules/snowball/snowball.controller.ts | 8 +++--- back/src/modules/user/user.controller.ts | 6 ++--- 5 files changed, 35 insertions(+), 29 deletions(-) diff --git a/back/src/common/guards/jwt.guard.ts b/back/src/common/guards/jwt.guard.ts index 0704186..5ffd402 100644 --- a/back/src/common/guards/jwt.guard.ts +++ b/back/src/common/guards/jwt.guard.ts @@ -5,7 +5,7 @@ import { Req, UnauthorizedException } from '@nestjs/common'; -import { JwtService } from '@nestjs/jwt'; +import { JwtService, TokenExpiredError } from '@nestjs/jwt'; import { Request } from 'express'; @Injectable() @@ -14,7 +14,8 @@ export class JWTGuard implements CanActivate { async canActivate(context: ExecutionContext): Promise { const request = context.switchToHttp().getRequest(); - const token = this.extractTokenFromHeader(request); + console.log(request); + const token = this.extractAccessToken(request); if (!token) { throw new UnauthorizedException(); } @@ -30,8 +31,22 @@ export class JWTGuard implements CanActivate { return true; } - private extractTokenFromHeader(@Req() req: Request): string | undefined { - const [type, token] = req.headers.authorization?.split(' ') ?? []; - return type === 'Bearer' ? token : undefined; + private extractAccessToken(@Req() req: Request): string | undefined { + const cookieHeader = req.headers.cookie; + console.log(cookieHeader); + if (!cookieHeader) { + return undefined; + } + + const cookies = cookieHeader.split(';').map(cookie => cookie.trim()); + const accessToken = cookies.find(cookie => + cookie.startsWith(`access_token=`) + ); + + if (accessToken) { + return accessToken.split('=')[1]; + } else { + throw new TokenExpiredError('Token expired', new Date()); + } } } diff --git a/back/src/common/util/swagger.ts b/back/src/common/util/swagger.ts index 37dc4f1..5ddfb61 100644 --- a/back/src/common/util/swagger.ts +++ b/back/src/common/util/swagger.ts @@ -28,16 +28,7 @@ export function setupSwagger(app: INestApplication): void { } } }) - .addBearerAuth( - { - type: 'http', - scheme: 'bearer', - bearerFormat: 'JWT', - name: 'JWT', - in: 'header' - }, - 'jwt-token' - ) + .addCookieAuth('access_token') .build(); const document = SwaggerModule.createDocument(app, config); SwaggerModule.setup('docs', app, document, { diff --git a/back/src/modules/message/message.controller.ts b/back/src/modules/message/message.controller.ts index 768e312..95b67ae 100644 --- a/back/src/modules/message/message.controller.ts +++ b/back/src/modules/message/message.controller.ts @@ -17,13 +17,13 @@ import { ApiTags, ApiOperation, ApiResponse, - ApiBearerAuth, ApiNotFoundResponse, ApiConflictResponse, ApiBadRequestResponse, ApiInternalServerErrorResponse, ApiGoneResponse, - ApiUnauthorizedResponse + ApiUnauthorizedResponse, + ApiCookieAuth } from '@nestjs/swagger'; import { ResCreateMessageDto } from './dto/response/res-create-message.dto'; import { MessageDto } from './dto/message.dto'; @@ -66,7 +66,7 @@ export class MessageController { } @UseGuards(JWTGuard) - @ApiBearerAuth('jwt-token') + @ApiCookieAuth('access_token') @Delete(':message_id') @HttpCode(204) @ApiOperation({ @@ -91,7 +91,7 @@ export class MessageController { } @UseGuards(JWTGuard) - @ApiBearerAuth('jwt-token') + @ApiCookieAuth('access_token') @Get('/') @HttpCode(200) @ApiOperation({ @@ -113,7 +113,7 @@ export class MessageController { } @UseGuards(JWTGuard) - @ApiBearerAuth('jwt-token') + @ApiCookieAuth('access_token') @Put('/:message_id/open') @HttpCode(200) @ApiOperation({ @@ -143,7 +143,7 @@ export class MessageController { } @UseGuards(JWTGuard) - @ApiBearerAuth('jwt-token') + @ApiCookieAuth('access_token') @Put('/:message_id/decoration') @ApiOperation({ summary: '메세지 장식 변경', @@ -173,7 +173,7 @@ export class MessageController { } @UseGuards(JWTGuard) - @ApiBearerAuth('jwt-token') + @ApiCookieAuth('access_token') @Put('/:message_id/location') @ApiOperation({ summary: '메세지 위치 변경', diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index baaa7dd..fab3b6c 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -17,7 +17,7 @@ import { ApiOperation, ApiCreatedResponse, ApiResponse, - ApiBearerAuth + ApiCookieAuth } from '@nestjs/swagger'; import { ReqCreateSnowballDto } from './dto/request/req-create-snowball.dto'; import { ReqUpdateSnowballDto } from './dto/request/req-update-snowball.dto'; @@ -34,7 +34,7 @@ export class SnowballController { constructor(private readonly snowballService: SnowballService) {} @UseGuards(JWTGuard) - @ApiBearerAuth('jwt-token') + @ApiCookieAuth('access_token') @Post() @HttpCode(201) @ApiOperation({ @@ -58,7 +58,7 @@ export class SnowballController { } @UseGuards(JWTGuard) - @ApiBearerAuth('jwt-token') + @ApiCookieAuth('access_token') @Put('/:snowball_id') @HttpCode(200) @ApiResponse({ @@ -109,7 +109,7 @@ export class SnowballController { } @UseGuards(JWTGuard) - @ApiBearerAuth('jwt-token') + @ApiCookieAuth('access_token') @Put('/:snowball_id/decoration') @ApiResponse({ status: 200, diff --git a/back/src/modules/user/user.controller.ts b/back/src/modules/user/user.controller.ts index fb4090f..d69799e 100644 --- a/back/src/modules/user/user.controller.ts +++ b/back/src/modules/user/user.controller.ts @@ -12,7 +12,7 @@ import { ApiTags, ApiOperation, ApiResponse, - ApiBearerAuth, + ApiCookieAuth, ApiBody } from '@nestjs/swagger'; import { UserService } from './user.service'; @@ -26,7 +26,7 @@ export class UserController { constructor(private readonly userService: UserService) {} @UseGuards(JWTGuard) - @ApiBearerAuth('jwt-token') + @ApiCookieAuth('access_token') @Get() @ApiOperation({ summary: '사용자 유저 조회 API', @@ -60,7 +60,7 @@ export class UserController { } @UseGuards(JWTGuard) - @ApiBearerAuth('jwt-token') + @ApiCookieAuth('access_token') @Put('/nickname') @ApiBody({ type: NicknameDto }) @ApiOperation({ From ee0e6dcc0062ca7755c941c782af443c480b1052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Fri, 1 Dec 2023 00:46:50 +0900 Subject: [PATCH 161/185] =?UTF-8?q?feat:=20guard=20&=20interceptor=20cooki?= =?UTF-8?q?e=20=EC=9D=BD=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/common/guards/jwt.guard.ts | 4 +--- ...equest.interceptor.ts => hasJwt.interceptor.ts} | 14 +++++++++----- back/src/common/interface/request.interface.ts | 1 - back/src/modules/snowball/snowball.controller.ts | 5 ++--- 4 files changed, 12 insertions(+), 12 deletions(-) rename back/src/common/interceptors/{jwtRequest.interceptor.ts => hasJwt.interceptor.ts} (66%) diff --git a/back/src/common/guards/jwt.guard.ts b/back/src/common/guards/jwt.guard.ts index 5ffd402..414ff0f 100644 --- a/back/src/common/guards/jwt.guard.ts +++ b/back/src/common/guards/jwt.guard.ts @@ -14,7 +14,6 @@ export class JWTGuard implements CanActivate { async canActivate(context: ExecutionContext): Promise { const request = context.switchToHttp().getRequest(); - console.log(request); const token = this.extractAccessToken(request); if (!token) { throw new UnauthorizedException(); @@ -33,9 +32,8 @@ export class JWTGuard implements CanActivate { private extractAccessToken(@Req() req: Request): string | undefined { const cookieHeader = req.headers.cookie; - console.log(cookieHeader); if (!cookieHeader) { - return undefined; + throw new UnauthorizedException(); } const cookies = cookieHeader.split(';').map(cookie => cookie.trim()); diff --git a/back/src/common/interceptors/jwtRequest.interceptor.ts b/back/src/common/interceptors/hasJwt.interceptor.ts similarity index 66% rename from back/src/common/interceptors/jwtRequest.interceptor.ts rename to back/src/common/interceptors/hasJwt.interceptor.ts index 2bd940e..cc8ddef 100644 --- a/back/src/common/interceptors/jwtRequest.interceptor.ts +++ b/back/src/common/interceptors/hasJwt.interceptor.ts @@ -8,18 +8,21 @@ import { Observable } from 'rxjs'; import { JwtService } from '@nestjs/jwt'; @Injectable() -export class JWTToRequestInterceptor implements NestInterceptor { +export class hasJWTInterceptor implements NestInterceptor { constructor(private readonly jwtService: JwtService) {} async intercept( context: ExecutionContext, next: CallHandler ): Promise> { - console.log('Before...'); - const request = context.switchToHttp().getRequest(); - const [type, token] = request.headers.authorization?.split(' ') ?? []; - if (type === 'Bearer' && token) { + const cookies = + request.headers.cookie?.split(';').map(cookie => cookie.trim()) ?? []; + const accessToken = cookies.find(cookie => + cookie.startsWith(`access_token=`) + ); + if (accessToken) { + const token = accessToken.split('=')[1]; request['hasToken'] = true; const payload = await this.jwtService.verify(token, { secret: process.env.JWT_ACCESS_SECRET @@ -27,6 +30,7 @@ export class JWTToRequestInterceptor implements NestInterceptor { request['user'] = payload; } else { + request['user'] = null; request['hasToken'] = false; } diff --git a/back/src/common/interface/request.interface.ts b/back/src/common/interface/request.interface.ts index 067973f..92a44a2 100644 --- a/back/src/common/interface/request.interface.ts +++ b/back/src/common/interface/request.interface.ts @@ -9,4 +9,3 @@ export interface JWTRequest extends Request { hasToken?: boolean; } -// 분리 diff --git a/back/src/modules/snowball/snowball.controller.ts b/back/src/modules/snowball/snowball.controller.ts index fab3b6c..4b50e3a 100644 --- a/back/src/modules/snowball/snowball.controller.ts +++ b/back/src/modules/snowball/snowball.controller.ts @@ -26,7 +26,7 @@ import { ResUpdateSnowballDto } from './dto/response/res-update-snowball.dto'; import { JWTGuard } from 'src/common/guards/jwt.guard'; import { UpdateMainDecoDto } from './dto/update-main-decoration.dto'; import { JWTRequest } from '../../common/interface/request.interface'; -import { JWTToRequestInterceptor } from '../../common/interceptors/jwtRequest.interceptor'; +import { hasJWTInterceptor } from '../../common/interceptors/hasJwt.interceptor'; @ApiTags('Snowball API') @Controller('snowball') @@ -84,9 +84,8 @@ export class SnowballController { return snowball; } - // 인터셉터 두개로 분리 @Get('/:snowball_id') - @UseInterceptors(JWTToRequestInterceptor) + @UseInterceptors(hasJWTInterceptor) @HttpCode(200) @ApiResponse({ status: 200, From f88374a7e37abc0381233b95c251fff15624f50b Mon Sep 17 00:00:00 2001 From: Mina Seo <96722691+esthel7@users.noreply.github.com> Date: Sun, 3 Dec 2023 19:33:39 +0900 Subject: [PATCH 162/185] Update README.md --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index bdaa8fd..e858a67 100644 --- a/README.md +++ b/README.md @@ -6,18 +6,18 @@ - 롤링페이퍼처럼 여러사람이 한 곳에 메시지를 작성 하는 아이디어📄 ## SSOCK 팀 -
J034 J064 J082
Front-End 나도 3D사이트,,
할 수 있다,,🔥
Front-End안녕하세요
저는 오승엽입니다
누군가는 해야하잖아🤯
Back-End 백린이
최진수입니다
Back-End
Front-End잘 부탁드려요
연말
-낭만사냥꾼-
나도 3D사이트,,
할 수 있다,,🔥
안녕하세요
저는 오승엽입니다
누군가는 해야하잖아🤯
안녕하세요
저는 오승엽입니다
누군가는
해야하잖아🤯
Back-End 백린이
최진수입니다
- - - - - +
J034J064J082J074J160
+ + + + + - - - - - + + + + +
J034J064J082J074J160
김찬우 From 4315c4213ef268a52db964c4f0e5252a0e260e09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Thu, 7 Dec 2023 17:58:06 +0900 Subject: [PATCH 163/185] Update README.md --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e858a67..79f4548 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 🎄 web11-SSOCK +![image](https://github.com/boostcampwm2023/web11-SSOCK/assets/83938394/b2258d3b-9e4c-4e82-a69f-090aceab71e2)# 🎄 web11-SSOCK ## 메인 아이디어 - 부스트캠프가 끝나는 시기에 크리스마스 감성이 가득한 사이트 제작🎅 @@ -49,3 +49,7 @@ ## [Wiki](https://github.com/boostcampwm2023/web11-SSOCK/wiki) ## [Notion](https://delicious-halloumi-7ae.notion.site/SSOCK-By-SSOCK-ada468a8b135435bb8acc1c50a2a9c0c?pvs=4) + +## 시스템 아키텍쳐 🔧 +![Web App Reference Architecture (1)](https://github.com/boostcampwm2023/web11-SSOCK/assets/83938394/3b1ca700-a415-4ac8-b080-e2091bace2ac) + From a633e8cf3dec238db0a1543dbc269a8c7c4c047d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Thu, 7 Dec 2023 17:58:21 +0900 Subject: [PATCH 164/185] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 79f4548..c4e71e6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![image](https://github.com/boostcampwm2023/web11-SSOCK/assets/83938394/b2258d3b-9e4c-4e82-a69f-090aceab71e2)# 🎄 web11-SSOCK +# 🎄 web11-SSOCK ## 메인 아이디어 - 부스트캠프가 끝나는 시기에 크리스마스 감성이 가득한 사이트 제작🎅 From cc5fb3aa30d45337d03b6c04b7e53d5b028f02ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=A1=ED=98=84=EC=9A=B0?= <83938394+yunuo46@users.noreply.github.com> Date: Thu, 7 Dec 2023 17:58:46 +0900 Subject: [PATCH 165/185] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c4e71e6..acb7b17 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,6 @@ ## [Notion](https://delicious-halloumi-7ae.notion.site/SSOCK-By-SSOCK-ada468a8b135435bb8acc1c50a2a9c0c?pvs=4) -## 시스템 아키텍쳐 🔧 +## 🔧 시스템 아키텍쳐 ![Web App Reference Architecture (1)](https://github.com/boostcampwm2023/web11-SSOCK/assets/83938394/3b1ca700-a415-4ac8-b080-e2091bace2ac) From 0d52a964ed463fba6eb5d81e945b3f787014a2f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jinsoo=20Choi=20=28=EC=B5=9C=EC=A7=84=EC=88=98=29?= Date: Thu, 7 Dec 2023 23:59:53 +0900 Subject: [PATCH 166/185] =?UTF-8?q?fix:=20=EB=B0=B1=EC=97=94=EB=93=9C=20?= =?UTF-8?q?=EA=B3=BC=EA=B1=B0=20=EC=9B=8C=ED=81=AC=ED=94=8C=EB=A1=9C?= =?UTF-8?q?=EC=9A=B0=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/backend.yml | 85 ----------------------------------- 1 file changed, 85 deletions(-) delete mode 100644 .github/workflows/backend.yml diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml deleted file mode 100644 index 805c3bb..0000000 --- a/.github/workflows/backend.yml +++ /dev/null @@ -1,85 +0,0 @@ -# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs - -name: Node.js CI - -on: - push: - branches: ["main"] - pull_request: - branches: ["main"] - -jobs: - # test: - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v4 - - # - name: Use Node.js 20.5.1 - # uses: actions/setup-node@v4 - # with: - # node-version: 20.5.1 - - # - name: Install package - # run: npm install - # working-directory: ./was - - # - name: npm build - # run: npm run build --if-present - # working-directory: ./was - - # - name: npm test - # run: npm test - # working-directory: ./was - build_docker: - needs: test - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - context: ./was - push: true - tags: ghcr.io/yunuo46/was_test:latest - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GHCR_TOKEN }} - - name: Build and push - uses: docker/build-push-action@v5 - with: - context: ./was - push: true - tags: ghcr.io/yunuo46/was_test:latest - deploy_docker: - needs: build_docker - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: SSH Version Check - run: ssh -V - - - name: Deploy to Server via SSH - uses: appleboy/ssh-action@master - with: - host: ${{ secrets.SERVER_HOST }} - username: ${{ secrets.SERVER_USERNAME }} - password: ${{ secrets.SERVER_PASSWORD }} - port: 22 - script: | - ssh -i ~/.ssh/id_rsa root@10.0.2.6 << 'EOF' - echo ${{ secrets.GHCR_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin - docker pull ghcr.io/yunuo46/was_test:latest - docker stop was_test || true - docker rm was_test || true - docker run -d --name was_test -p 3000:3000 ghcr.io/yunuo46/was_test:latest From 373003703d3ea1e6376478a848d4b366a54176fd Mon Sep 17 00:00:00 2001 From: ChanWoo Kim Date: Fri, 8 Dec 2023 15:59:29 +0900 Subject: [PATCH 167/185] docs: add README tech stack --- README.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/README.md b/README.md index acb7b17..bc4464b 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,76 @@
+## 기술스택 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
분류기술 스택
+

공통

+
+ +
+

프론트엔드

+
+ + +
+

백엔드

+
+ + + + +
+

패키지 매니저

+
+ +
+

배포

+
+ + + + +
+

협업

+
+ + + +
+ ## [Wiki](https://github.com/boostcampwm2023/web11-SSOCK/wiki) ## [Notion](https://delicious-halloumi-7ae.notion.site/SSOCK-By-SSOCK-ada468a8b135435bb8acc1c50a2a9c0c?pvs=4) From 6a4ad2bdcbd157b1eb407f1412c69dcf8168227d Mon Sep 17 00:00:00 2001 From: ChanWoo Kim Date: Fri, 8 Dec 2023 18:08:50 +0900 Subject: [PATCH 168/185] Delete .DS_Store --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 027a2aeb0fbb7fa0680e1c7f67b680db86bab69d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%}T>S5Z-O0CKMqDg&r5Y7Ho|O;w8lT0!H+pQWH}&G-gYa+CwSitS{t~_&m<+ zZp31}ir5+0{pNQ!`$6`HF~);w(qqhJjM>l-IVvjz-77;4lZ?o5jCfXz<4ne2znR!y z2mE%6#Vlg?Z1nZ}<8hW2Ww-mz8%=9tbIZ2vmVFyO%2`-O<+KQ*$u(LRQf6_jNAYDk zoDJNaQ<;}hnhz(cAWepla&wjDiJS#;nkR*-4RyeF9B1IR=X1~VI^wX`TXe+y_@E2A zceGeI_U_*P$@yTEJ>~L66Uu>aCEEsTcm?HiJ Date: Fri, 8 Dec 2023 18:41:39 +0900 Subject: [PATCH 169/185] docs: add README detail --- README.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/README.md b/README.md index bc4464b..2ef5d47 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,41 @@ - 부스트캠프가 끝나는 시기에 크리스마스 감성이 가득한 사이트 제작🎅 - 크리스마스에 사람들끼리 속마음을 주고받으면 어떨까❓ - 롤링페이퍼처럼 여러사람이 한 곳에 메시지를 작성 하는 아이디어📄 +

+ +
+ +### 스노우볼을 이리저리 구경 해보세요 ! 🎄 + +장식을 클릭하면 메세지를 확인 할 수 있어요 💝 + +
+ +

+ +

+ +### 나만의 스노우볼을 만들어 보세요 ! ⛄ + +장식과 색깔을 선택해 개성있는 스노우 볼을 만들고 공유해 보세요 🔮 + +
+ +

+ +

+ +### 공유 받은 스노우볼을 꾸며주세요 ! 🎁 + +이쁜 장식을 만들어 따뜻한 말을 담은 메세지를 남겨보세요 ! 💌 + +
+ +

+ +
+ +
## SSOCK 팀 From 8508cfba203ceff20c1c17447a6eead7b7121c9d Mon Sep 17 00:00:00 2001 From: ChanWoo Kim Date: Sat, 9 Dec 2023 02:26:21 +0900 Subject: [PATCH 170/185] Update README.md --- README.md | 52 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2ef5d47..5290453 100644 --- a/README.md +++ b/README.md @@ -4,38 +4,59 @@ - 부스트캠프가 끝나는 시기에 크리스마스 감성이 가득한 사이트 제작🎅 - 크리스마스에 사람들끼리 속마음을 주고받으면 어떨까❓ - 롤링페이퍼처럼 여러사람이 한 곳에 메시지를 작성 하는 아이디어📄 + +## [서비스 링크 - mysnowball.kr](https://www.mysnowball.kr) +

### 스노우볼을 이리저리 구경 해보세요 ! 🎄 -장식을 클릭하면 메세지를 확인 할 수 있어요 💝 +**장식을 클릭하면 메세지를 확인 할 수 있어요 💝**


+스노우볼을 클릭하면 내부로 들어가서 장식 클릭이 가능해집니다. + +장식을 클릭하면 메세지가 보여요. + +읽지 않은 메세지는 ❗ 표시가 떠있어요. +

### 나만의 스노우볼을 만들어 보세요 ! ⛄ -장식과 색깔을 선택해 개성있는 스노우 볼을 만들고 공유해 보세요 🔮 +**장식과 색깔을 선택해 개성있는 스노우 볼을 만들고 공유해 보세요 🔮**


+원하는 장식과 색깔을 선택 할 수 있어요. + +스노우볼의 이름을 직접 정해줄 수 있어요. + +링크를 마음을 전달 받고 싶은 사람들에게 공유해요. +

### 공유 받은 스노우볼을 꾸며주세요 ! 🎁 -이쁜 장식을 만들어 따뜻한 말을 담은 메세지를 남겨보세요 ! 💌 +**이쁜 장식을 만들어 따뜻한 말을 담은 메세지를 남겨보세요 ! 💌**


+공유 받은 링크를 통해 스노우볼 주인의 장식을 구경해요. + +스노우볼에 들어갈 장식을 직접 선택해요. + +전하고 싶은 마음을 메세지에 담아 장식과 함께 전달해요. +
@@ -151,10 +172,31 @@
+## 🔧 시스템 아키텍쳐 +![Web App Reference Architecture (1)](https://github.com/boostcampwm2023/web11-SSOCK/assets/83938394/3b1ca700-a415-4ac8-b080-e2091bace2ac) + +## 프로젝트 진행 + +- [🪧기획서](https://delicious-halloumi-7ae.notion.site/1562397628e946af8079141976c2c05f) +- [🎨디자인](https://www.figma.com/file/gjkpvDvtIXvIbQeYnRAxXT/%EC%8A%A4%EB%85%B8%EC%9A%B0%EB%B3%BC-ssock-%EB%82%B4-%EB%A7%88%EC%9D%8C?type=design&node-id=0%3A1&mode=design&t=syUy3ZT9jZUE0Zjm-1) +- [🧑‍💻트러블슈팅 및 기술로그](https://delicious-halloumi-7ae.notion.site/05ad5353254b49d1aef2021f773f79f0) +- [📓그라운드 룰](https://delicious-halloumi-7ae.notion.site/5755ab5457d843129355de5b4e22a538) +- [🏠깃허브 컨벤션](https://delicious-halloumi-7ae.notion.site/35419f77b8fb4cf0b6dc62776540062a) +- [☑️코딩 및 브랜치 컨벤션](https://delicious-halloumi-7ae.notion.site/TODO-3e94a37008054e1dbf069924e4b326d1) +- [🔙백로그](https://delicious-halloumi-7ae.notion.site/bb4f7bbba3b147a39cd425c70a187049) +- [📘회의록](https://delicious-halloumi-7ae.notion.site/5e446ce68cb84ead801fd98eb9419811?pvs=4) + +## 기술적 도전 + +작성예정 + +
+ +더 자세한 기록은 노션과 위키를 확인해주세요. + ## [Wiki](https://github.com/boostcampwm2023/web11-SSOCK/wiki) ## [Notion](https://delicious-halloumi-7ae.notion.site/SSOCK-By-SSOCK-ada468a8b135435bb8acc1c50a2a9c0c?pvs=4) -## 🔧 시스템 아키텍쳐 -![Web App Reference Architecture (1)](https://github.com/boostcampwm2023/web11-SSOCK/assets/83938394/3b1ca700-a415-4ac8-b080-e2091bace2ac) + From 4bd7884a887017547f5688f9d99681d81b7b0303 Mon Sep 17 00:00:00 2001 From: kcwww Date: Sat, 9 Dec 2023 02:33:17 +0900 Subject: [PATCH 171/185] docs: add href README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5290453..48fa8e3 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ - 크리스마스에 사람들끼리 속마음을 주고받으면 어떨까❓ - 롤링페이퍼처럼 여러사람이 한 곳에 메시지를 작성 하는 아이디어📄 -## [서비스 링크 - mysnowball.kr](https://www.mysnowball.kr) +[서비스 링크 - mysnowball.kr 🔮](https://www.mysnowball.kr){:target="_blank"}

From 0c2325c1381a16c1b390641060f672735a72550b Mon Sep 17 00:00:00 2001 From: ChanWoo Kim Date: Sat, 9 Dec 2023 02:35:27 +0900 Subject: [PATCH 172/185] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 48fa8e3..cf18314 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ - 크리스마스에 사람들끼리 속마음을 주고받으면 어떨까❓ - 롤링페이퍼처럼 여러사람이 한 곳에 메시지를 작성 하는 아이디어📄 -[서비스 링크 - mysnowball.kr 🔮](https://www.mysnowball.kr){:target="_blank"} +## [서비스 링크 - mysnowball.kr 🔮](https://www.mysnowball.kr)

From 6952a2cfd7faf17ae3dfdc024fb156f8209144e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jinsoo=20Choi=20=28=EC=B5=9C=EC=A7=84=EC=88=98=29?= Date: Mon, 11 Dec 2023 21:40:04 +0900 Subject: [PATCH 173/185] =?UTF-8?q?docs:=20=EB=A6=AC=EB=93=9C=EB=AF=B8=20?= =?UTF-8?q?=EC=8B=9C=EC=8A=A4=ED=85=9C=20=EC=95=84=ED=82=A4=ED=85=8D?= =?UTF-8?q?=EC=B3=90=20=EB=8F=84=ED=98=95=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cf18314..9e726e2 100644 --- a/README.md +++ b/README.md @@ -173,7 +173,7 @@ ## 🔧 시스템 아키텍쳐 -![Web App Reference Architecture (1)](https://github.com/boostcampwm2023/web11-SSOCK/assets/83938394/3b1ca700-a415-4ac8-b080-e2091bace2ac) +![Web App Reference Architecture](https://github.com/boostcampwm2023/web11-SSOCK/assets/33882299/d761bf8a-0915-458f-817e-972345a67016) ## 프로젝트 진행 From 69e4bdbf9470be119c3607815fad7367cd5c585a Mon Sep 17 00:00:00 2001 From: ChanWoo Kim Date: Mon, 11 Dec 2023 21:54:54 +0900 Subject: [PATCH 174/185] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9e726e2..84ce514 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,9 @@

프론트엔드

- + + + @@ -167,6 +169,7 @@ + From dca77eebb51bb07ece162e54bbab1e506d67de24 Mon Sep 17 00:00:00 2001 From: Mina Seo <96722691+esthel7@users.noreply.github.com> Date: Tue, 12 Dec 2023 00:02:01 +0900 Subject: [PATCH 175/185] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 84ce514..e350127 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # 🎄 web11-SSOCK ## 메인 아이디어 -- 부스트캠프가 끝나는 시기에 크리스마스 감성이 가득한 사이트 제작🎅 - 크리스마스에 사람들끼리 속마음을 주고받으면 어떨까❓ - 롤링페이퍼처럼 여러사람이 한 곳에 메시지를 작성 하는 아이디어📄 +- 반응형 3D로 입체감있는 스노우볼 제작🔮 ## [서비스 링크 - mysnowball.kr 🔮](https://www.mysnowball.kr) From fa4a4dcabdc797a14ece4dc3bb09519463d97cb9 Mon Sep 17 00:00:00 2001 From: ChanWoo Kim Date: Wed, 13 Dec 2023 09:35:03 +0900 Subject: [PATCH 176/185] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e350127..e85d37c 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@
-

+

공유 받은 링크를 통해 스노우볼 주인의 장식을 구경해요. From 3d481b2df68282f6a0a342e6755654d599b166a6 Mon Sep 17 00:00:00 2001 From: ChanWoo Kim Date: Wed, 13 Dec 2023 21:49:41 +0900 Subject: [PATCH 177/185] Update README.md --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e85d37c..0a8597d 100644 --- a/README.md +++ b/README.md @@ -176,7 +176,12 @@ ## 🔧 시스템 아키텍쳐 -![Web App Reference Architecture](https://github.com/boostcampwm2023/web11-SSOCK/assets/33882299/d761bf8a-0915-458f-817e-972345a67016) + +![Web_App_Reference_Architecture_7](https://github.com/boostcampwm2023/web11-SSOCK/assets/98443541/84c3d483-04b0-4484-9c7e-54b58708a648) + +## 기술적 도전 + +작성예정 ## 프로젝트 진행 @@ -189,9 +194,7 @@ - [🔙백로그](https://delicious-halloumi-7ae.notion.site/bb4f7bbba3b147a39cd425c70a187049) - [📘회의록](https://delicious-halloumi-7ae.notion.site/5e446ce68cb84ead801fd98eb9419811?pvs=4) -## 기술적 도전 -작성예정
From be3b9cc0084529d19a0a6023a11be54748f67442 Mon Sep 17 00:00:00 2001 From: ChanWoo Kim Date: Wed, 13 Dec 2023 22:12:09 +0900 Subject: [PATCH 178/185] Update README.md --- README.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0a8597d..3b48c54 100644 --- a/README.md +++ b/README.md @@ -181,7 +181,31 @@ ## 기술적 도전 -작성예정 +
+ +### 프론트엔드 + +이번 프로젝트를 통해 가장 중점적으로 생각한 부분은 `실제 사용자들이 사용할 서비스를 만들자` 였습니다. + +프론트 엔드 팀원 모두 `React` 에 익숙하지 못했고, 어려운 기술적인 부분보다는 기초적인 부분에 충실하게 학습하여 구현을 해나가는것을 목표로 삼았습니다. + +- ### 다양한 기기에서의 호환성 + +개발환경을 PC 환경에서 크롬으로 진행하며 반응형으로 프로젝트를 진행하였습니다. + +간단한 프로토타입을 완성 후, 빠른 배포를 통해 여러 기기에서의 UI를 확인해보고 성능을 테스트 해보았습니다. + +그 와중, 3D 모델 렌더링 과정에서의 최적화 문제를 발견하였고, `Three.js` 의 모델링의 `Mesh` 를 조절하고 rAF 기반인 `useFrame` 을 여러개를 사용하지 않고 하나의 컴포넌트로 묶어 최적화를 진행하여 갤럭시 S10 기준 GPU 를 98% 에서 70% 가량으로 렌더링 성능을 낮추었습니다. + +다음으로, 아이폰 `IOS` 17 버전 이후로 사파리 어플리케이션에서 문제가 나타나게 되었고, 기존 화면의 크기를 자동으로 계산해주는 `100vh` 에서 직접 렌더링 되는 화면을 계산해 카카오톡, 인스타그램과 같은 임베드 웹까지 적절하게 렌더링 될수 있도록 수정하였습니다. + +[🖥️100vh 기기문제](https://delicious-halloumi-7ae.notion.site/100vh-7af4bdb4c46c46268d818217b3fd53cb?pvs=4) + +다음으로 매번 배포해서 모바일 환경을 실시간으로 CSS 를 디버깅하기에 어려움이 있어 여러 방법을 도입하였습니다. + + + + ## 프로젝트 진행 From cb51e83e71976ffe62f0005c7466ae806cda5afc Mon Sep 17 00:00:00 2001 From: ChanWoo Kim Date: Wed, 13 Dec 2023 23:15:22 +0900 Subject: [PATCH 179/185] Update README.md --- README.md | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3b48c54..2e24b45 100644 --- a/README.md +++ b/README.md @@ -181,8 +181,6 @@ ## 기술적 도전 -
- ### 프론트엔드 이번 프로젝트를 통해 가장 중점적으로 생각한 부분은 `실제 사용자들이 사용할 서비스를 만들자` 였습니다. @@ -203,6 +201,35 @@ 다음으로 매번 배포해서 모바일 환경을 실시간으로 CSS 를 디버깅하기에 어려움이 있어 여러 방법을 도입하였습니다. +- 구글 크롬 스마트폰 모바일 개발자 도구 (안드로이드) +- 유료 프로그램 +- vite 로컬 호스트 연결 + +이렇게 세가지 방법을 찾아보았고 그중에 가장 접근성이 좋은 vite 로컬 호스트 연결을 선택하였습니다. + +`vite.config.ts` 의 host를 설정해 같은 네트워크를 공유하여 실시간으로 모바일 환경을 볼 수 있었습니다. + +
+
+ react-components +
+
+ +- ### 리렌더링 최적화 + +SSOCK 팀 프론트엔드에서 설계한 컴포넌트 구조의 간략한 시각화는 다음과 같습니다. + +
+
+ react-components +
+
+ +크게 `Three.js` 로 렌더링한 Canvas 컴포넌트와 UI 를 구분지어 설계하였습니다. + + + + From c69857eefe5a8e65ca8a0a6f2201d1d831cd7a7f Mon Sep 17 00:00:00 2001 From: ChanWoo Kim Date: Thu, 14 Dec 2023 00:50:47 +0900 Subject: [PATCH 180/185] Update README.md --- README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/README.md b/README.md index 2e24b45..3f6b552 100644 --- a/README.md +++ b/README.md @@ -227,6 +227,32 @@ SSOCK 팀 프론트엔드에서 설계한 컴포넌트 구조의 간략한 시 크게 `Three.js` 로 렌더링한 Canvas 컴포넌트와 UI 를 구분지어 설계하였습니다. +3D 모델을 렌더링 하는것은 성능에 큰 영향이 있었고, 프로젝트 기준 애니메이션 효과가 많이 들어가 리렌더링을 하게 된다면 애니메이션 효과들이 처음부터 시작되어 (위 소개 GIF 예시로 장식이 다시 떨어지는 문제) 사용자 경험에 부정적 영향을 줄 수 있었습니다. + +따라서 리렌더링에 사용되는 `useState` 훅을 UI 내부에서 사용하려 시도하였고, 그로인해 Canvas 컴포넌트와의 `depth` 차이에 대해 깊게 고민하고 사용하게 되었습니다. + +또한 기존 React 에 기본기에 충실하기 위해 다른 상태관리 라이브러리를 사용하지 않고 `useContext` 훅을 사용해 상태관리를 하였습니다. + +각 라우팅된 페이지들의 공통적으로 사용되는 데이터들을 정의해주고 `Provider` 로 하위 컴포넌트들을 감싸 Canvas 와 UI 모두 동일한 데이터를 제공하였습니다. + +그로인해 Canvas로 렌더링된 장식 모델에 대한 이벤트처리를 UI 에서 처리할수 있어 Canvas 를 리렌더링 하지 않고 정상적으로 메세지를 띄울수 있었습니다. + +하지만 반대의 경우도 고려를 해야할 필요가 생기게 되어 문제가 되었습니다. + +읽지않은 메세지의 경우 Canvas 에서 3D 모델 ❗ 로 렌더링 하였는데, 장식을 클릭하였을때 UI 와 Canvas 모두 리렌더링을 동시에 해야 하는 경우가 생기게 되었고, 메세지를 읽을 때마다 3D 모델이 리렌더링 되어 다시 떨어지게 되었습니다. + +이때 컴포넌트의 `props` 를 비교해 이전 값과 같으면 리렌더링을 하지 않는 **`React.memo`** 고차 컴포넌트를 사용하여 해결하였습니다. + +
+
+ beforeReactMemo + afterReactMemo +
+
+ +[😧 useContext 상태관리](https://delicious-halloumi-7ae.notion.site/useContext-3da416204dc24f3b879e3520241a2d45?pvs=4) + +[📝 React.memo 를 통한 최적화](https://delicious-halloumi-7ae.notion.site/React-memo-223350a204a84227bfb100d424f5b656?pvs=4) From 8d6db505f8f1e7b199ccbd598bebcd35b7cdebe4 Mon Sep 17 00:00:00 2001 From: ChanWoo Kim Date: Thu, 14 Dec 2023 01:33:49 +0900 Subject: [PATCH 181/185] Update README.md --- README.md | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3f6b552..8c2f64c 100644 --- a/README.md +++ b/README.md @@ -244,19 +244,55 @@ SSOCK 팀 프론트엔드에서 설계한 컴포넌트 구조의 간략한 시 이때 컴포넌트의 `props` 를 비교해 이전 값과 같으면 리렌더링을 하지 않는 **`React.memo`** 고차 컴포넌트를 사용하여 해결하였습니다.
-
- beforeReactMemo - afterReactMemo -
+ + + + + + + +
React.memo 적용 전React.memo 적용 후

+ + [😧 useContext 상태관리](https://delicious-halloumi-7ae.notion.site/useContext-3da416204dc24f3b879e3520241a2d45?pvs=4) [📝 React.memo 를 통한 최적화](https://delicious-halloumi-7ae.notion.site/React-memo-223350a204a84227bfb100d424f5b656?pvs=4) +- ### 사용자 경험 최적화 + +네이버 부스트캠프 챌린지때 읽었던 `함께 자라기` 책을 읽고 애자일 방법론에 대해 알게 되었고, 팀원들과 함께 이번 프로젝트에 적용해보기로 결정하였습니다. + +3주차 부터 프로토타입이 나오게 되면서 개발자들의 입장과 사용자들의 입장 차이가 상당히 다르다는 것을 경험하게 되었습니다. + +
+
+ 예시사진 + 예시사진 + 예시사진 +
+
+ +피드백 수용한 사용자 편의성 개선 +
+ + + + + + + + + + + +
피드백 수용 전피드백 수용 후
+
+매주 여러 사용자들에게 피드백을 받으며 프로젝트를 보완하고 수정하였습니다. From 0156cfbc982db549a9c0240e4280cfa08e9a17e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jinsoo=20Choi=20=28=EC=B5=9C=EC=A7=84=EC=88=98=29?= Date: Thu, 14 Dec 2023 23:27:22 +0900 Subject: [PATCH 182/185] =?UTF-8?q?docs:=20=EB=A6=AC=EB=93=9C=EB=AF=B8=20B?= =?UTF-8?q?E=20=EA=B8=B0=EC=88=A0=EC=A0=81=EB=8F=84=EC=A0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8c2f64c..146b170 100644 --- a/README.md +++ b/README.md @@ -282,19 +282,45 @@ SSOCK 팀 프론트엔드에서 설계한 컴포넌트 구조의 간략한 시 피드백 수용 전 피드백 수용 후 - - + + - - + +
매주 여러 사용자들에게 피드백을 받으며 프로젝트를 보완하고 수정하였습니다. +--- +### BE 기술적 도전 + +저희 백엔드 팀원이 이번 프로젝트를 통해 가장 중점적으로 생각한 부분은 많은 이용자들을 고려한 서버 구성 및 효율적인 설계입니다 + +백엔드 팀원 모두 실제 배포 및 Nest.js가 처음이었고, 새로운 기술들을 도입하기 보다는 기존에 많이 사용하는 기술 스택을 더 깊이있게 공부하며 사용하는 것을 목표로 잡았습니다 + +- ### 인프라 설계 + +NCP를 이용하여 실제 사용되는 인프라 구조와 비슷하게 백엔드 인프라를 구축하는것이 저희의 목표였습니다. + +VPC안에 Nginx를 실행하는 웹서버를 공개 서브넷에 빼주고 WAS서버와 데이터베이스 서버를 비공개 서브넷에 넣어주었습니다. + +비공개 서브넷을 사용해서 백엔드 서버와 데이터베이스의 외부접근을 막아줌으로 1차 보호를 해주었습니다. + +CI/CD를 구성하는 과정에서 백엔드서버가 비공개 서브넷에 포함되어있어 백엔드 서버에 배포가 되지 않는 에러가 발생했습니다. 처음에는 VPC를 완전히 이해하지 못한 상황이라 해당 에러가 뜨는 이유를 찾지 못했습니다. 면밀한 검사 후 문제를 찾았고 백엔드 서버의 배포를 위해서 NAT 게이트웨이를 추가해줘서 외부에서의 incoming 통신은 차단하지만 백엔드서버에서의 outgoing 통신은 열어주어서 배포를 할 수 있었습니다. + + + +- ### 악성 사용자 예방 + +유사한 다른 프로젝트를 참고하니, DDOS 공격으로 서버에 과부하가 걸리거나 예상치 못한 비용이 나오는 등의 문제가 있었습니다. 저희는 이를 예방하기 위해 ip별로 rate-limiting을 적용하여 요청이 비정상적으로 몰리는 ip를 차단했습니다 + +- ### 쿼리 최적화 + +TypeORM을 사용하다보니 편리한 내장 함수에 의존하게 되어 실제로 쿼리가 어떻게 전송되고 설계되는 지 명확하지가 않았습니다. 그래서 저희는 쿼리 로그를 기록하며 필요하다면 rawQuery를 설계하여 서비스 로직을 구성했습니다. ## 프로젝트 진행 From 6facf58f8252100b1881aa2b0e2fe4185b5dc564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jinsoo=20Choi=20=28=EC=B5=9C=EC=A7=84=EC=88=98=29?= Date: Thu, 14 Dec 2023 23:34:17 +0900 Subject: [PATCH 183/185] =?UTF-8?q?docs:=20=EB=A6=AC=EB=93=9C=EB=AF=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 146b170..00476fd 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@
-

+

스노우볼을 클릭하면 내부로 들어가서 장식 클릭이 가능해집니다. @@ -33,7 +33,7 @@
-

+

원하는 장식과 색깔을 선택 할 수 있어요. @@ -49,7 +49,7 @@
-

+

공유 받은 링크를 통해 스노우볼 주인의 장식을 구경해요. @@ -177,7 +177,7 @@ ## 🔧 시스템 아키텍쳐 -![Web_App_Reference_Architecture_7](https://github.com/boostcampwm2023/web11-SSOCK/assets/98443541/84c3d483-04b0-4484-9c7e-54b58708a648) + ## 기술적 도전 @@ -296,7 +296,7 @@ SSOCK 팀 프론트엔드에서 설계한 컴포넌트 구조의 간략한 시 --- -### BE 기술적 도전 +### 백엔드 기술적 도전 저희 백엔드 팀원이 이번 프로젝트를 통해 가장 중점적으로 생각한 부분은 많은 이용자들을 고려한 서버 구성 및 효율적인 설계입니다 @@ -312,7 +312,7 @@ VPC안에 Nginx를 실행하는 웹서버를 공개 서브넷에 빼주고 WAS CI/CD를 구성하는 과정에서 백엔드서버가 비공개 서브넷에 포함되어있어 백엔드 서버에 배포가 되지 않는 에러가 발생했습니다. 처음에는 VPC를 완전히 이해하지 못한 상황이라 해당 에러가 뜨는 이유를 찾지 못했습니다. 면밀한 검사 후 문제를 찾았고 백엔드 서버의 배포를 위해서 NAT 게이트웨이를 추가해줘서 외부에서의 incoming 통신은 차단하지만 백엔드서버에서의 outgoing 통신은 열어주어서 배포를 할 수 있었습니다. - + - ### 악성 사용자 예방 From fc49fad4db7737df81fdb32522ce0282630a8b65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jinsoo=20Choi=20=28=EC=B5=9C=EC=A7=84=EC=88=98=29?= Date: Thu, 14 Dec 2023 23:39:27 +0900 Subject: [PATCH 184/185] =?UTF-8?q?docs:=20=EB=AA=BD=EA=B3=A0=EB=94=94?= =?UTF-8?q?=EB=B9=84=20=EC=95=84=EC=9D=B4=EC=BD=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 00476fd..1650927 100644 --- a/README.md +++ b/README.md @@ -138,6 +138,7 @@ + From 8fd80ddb7a446c1add0ddf56eddeaf9f544df4b8 Mon Sep 17 00:00:00 2001 From: ChanWoo Kim Date: Fri, 15 Dec 2023 14:06:23 +0900 Subject: [PATCH 185/185] Update README.md --- README.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/README.md b/README.md index 1650927..dd1ee51 100644 --- a/README.md +++ b/README.md @@ -267,13 +267,7 @@ SSOCK 팀 프론트엔드에서 설계한 컴포넌트 구조의 간략한 시 3주차 부터 프로토타입이 나오게 되면서 개발자들의 입장과 사용자들의 입장 차이가 상당히 다르다는 것을 경험하게 되었습니다. -
-
- 예시사진 - 예시사진 - 예시사진 -
-
+ 피드백 수용한 사용자 편의성 개선