From c42ae865772fd9c5d6a9256c53d88813a35d7d1a Mon Sep 17 00:00:00 2001 From: baturs Date: Tue, 22 Jul 2025 17:55:19 +0900 Subject: [PATCH 01/38] Part1 mission2 --- mission2/.gitignore | 1 + mission2/Prettier | 0 mission2/README.md | 1 + mission2/eslint.config.js | 9 + mission2/package-lock.json | 1386 ++++++++++++++++++++++++++++++++ mission2/package.json | 20 + mission2/src/Article.js | 13 + mission2/src/ArticleService.js | 63 ++ mission2/src/Product.js | 63 ++ mission2/src/ProductService.js | 89 ++ mission2/src/README.md | 2 + mission2/src/main.js | 107 +++ 12 files changed, 1754 insertions(+) create mode 100644 mission2/.gitignore create mode 100644 mission2/Prettier create mode 100644 mission2/README.md create mode 100644 mission2/eslint.config.js create mode 100644 mission2/package-lock.json create mode 100644 mission2/package.json create mode 100644 mission2/src/Article.js create mode 100644 mission2/src/ArticleService.js create mode 100644 mission2/src/Product.js create mode 100644 mission2/src/ProductService.js create mode 100644 mission2/src/README.md create mode 100644 mission2/src/main.js diff --git a/mission2/.gitignore b/mission2/.gitignore new file mode 100644 index 000000000..b512c09d4 --- /dev/null +++ b/mission2/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/mission2/Prettier b/mission2/Prettier new file mode 100644 index 000000000..e69de29bb diff --git a/mission2/README.md b/mission2/README.md new file mode 100644 index 000000000..af16321a8 --- /dev/null +++ b/mission2/README.md @@ -0,0 +1 @@ +# codeit-demo diff --git a/mission2/eslint.config.js b/mission2/eslint.config.js new file mode 100644 index 000000000..cdc890aba --- /dev/null +++ b/mission2/eslint.config.js @@ -0,0 +1,9 @@ +import js from "@eslint/js"; +import globals from "globals"; +import { defineConfig } from "eslint/config"; + + +export default defineConfig([ + { files: ["**/*.{js,mjs,cjs}"], plugins: { js }, extends: ["js/recommended"] }, + { files: ["**/*.{js,mjs,cjs}"], languageOptions: { globals: globals.browser } }, +]); diff --git a/mission2/package-lock.json b/mission2/package-lock.json new file mode 100644 index 000000000..adbed4efe --- /dev/null +++ b/mission2/package-lock.json @@ -0,0 +1,1386 @@ +{ + "name": "-test", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "-test", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "axios": "^1.10.0" + }, + "devDependencies": { + "eslint": "^9.31.0", + "prettier": "^3.6.2" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/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, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", + "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", + "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.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": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.31.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.31.0.tgz", + "integrity": "sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.3.tgz", + "integrity": "sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.15.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "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, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "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, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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, + "license": "Python-2.0" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", + "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.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, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "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/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==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "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, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "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, + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.31.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.31.0.tgz", + "integrity": "sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.0", + "@eslint/core": "^0.15.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.31.0", + "@eslint/plugin-kit": "^0.3.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "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, + "license": "MIT", + "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": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", + "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "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, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "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, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "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, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "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==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.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, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.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, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/mission2/package.json b/mission2/package.json new file mode 100644 index 000000000..7ae55aa2c --- /dev/null +++ b/mission2/package.json @@ -0,0 +1,20 @@ +{ + "type": "module", + "name": "-test", + "version": "1.0.0", + "main": "main.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "axios": "^1.10.0" + }, + "devDependencies": { + "eslint": "^9.31.0", + "prettier": "^3.6.2" + } +} diff --git a/mission2/src/Article.js b/mission2/src/Article.js new file mode 100644 index 000000000..eeda0fb08 --- /dev/null +++ b/mission2/src/Article.js @@ -0,0 +1,13 @@ +class Article { + constructor(title, content, writer, likeCount ) { + this.title = title; + this.content = content; + this.writer = writer; + this.likeCount = likeCount; + this.createdAt = new Date(); + } + + like() { + likeCount ++; + } +} diff --git a/mission2/src/ArticleService.js b/mission2/src/ArticleService.js new file mode 100644 index 000000000..e9223fbea --- /dev/null +++ b/mission2/src/ArticleService.js @@ -0,0 +1,63 @@ +export async function getArticleList(params) { + const url = new URL(`https://panda-market-api-crud.vercel.app/articles`); + Object.keys(params).forEach((key) => + url.searchParams.append(key, params[key]) + ); + + const res = await fetch(url); + const data = await res.json(); + return data; +} + +export async function getArticle() { + const res = await fetch (`https://panda-market-api-crud.vercel.app/articles`); + const data = await res.json(); + return data; +} + +export async function createArticle(articleData) { + const res = await fetch(`https://panda-market-api-crud.vercel.app/articles`, { + method: 'POST', + body: JSON.stringify(articleData), + headers: { + 'Content-Type': 'application/json', + }, + }); + + const data = await res.json(); + return data; +} + +export async function patchArticle(id, articleData) { + const res = await fetch(`https://panda-market-api-crud.vercel.app/articles/${id}`, { + method: 'PATCH', + body: JSON.stringify(articleData), + headers: { + 'Content-Type': 'application/json' + }, + }); + const data = await res.json(); + return data; +} + +export async function deleteArticle(id) { + const res = await fetch(`https://panda-market-api-crud.vercel.app/articles/${id}`, { + method: 'DELETE' + }); + const data = await res.json(); + return data; +} + + import axios from 'axios'; + + axios.post(`https://panda-market-api-crud.vercel.app/articles`, { + title:'게시글 작성 테스트', + content: '게시글 작성 테스트', + image: 'https://example.com/...' + }) + .then(response => { + console.log('응답 데이터:', response.data); + }) + .catch(error => { + console.error('에러 발생:', error); + }); \ No newline at end of file diff --git a/mission2/src/Product.js b/mission2/src/Product.js new file mode 100644 index 000000000..ecaa95aa2 --- /dev/null +++ b/mission2/src/Product.js @@ -0,0 +1,63 @@ +class Product { + constructor(name, description, price, tags, images, favoriteCount) { + this.name = name; + this.description = description; + this.price = price; + this.tags = tags; + this.images = images; + this.favoriteCount = favoriteCount + } + + favorite() { + favoriteCount ++; + } +} + +class ElectronicProduct extends Product{ + constructor(name, description, price, tags, images, favoriteCount, manufacturer) { + super(name, description, price, tags, images, favoriteCount); + this.manufacturer = manufacturer; + } +} + +import { getProductList, getProduct, createProduct, patchProduct } from "./ProductService.js"; + +function addNewProduct(products) { + const { name, description, price, tags, images, favoriteCount } = product; + const newProduct = { + id: products.length + 1, + name, + description, + price, + tags, + images, + favoriteCount, + }; + productsInput.push(newProduct); +} + +const productsInput = await getProduct(); + +console.log(productsInput); + +const products = productsInput; + +console.log(products); + +const electronicProduct = []; + +// productsInput.list.forEach((product) => { +// if(product.tags.find((element) => element === '전자제품')) { +// electronicProduct.push(product); +// } +// }); + +// console.log(electronicProduct); + +productsInput.list.forEach((product) => { + if(product.tags.includes('전자제품')) { + electronicProduct.push(product); + } +}); + +console.log(electronicProduct); \ No newline at end of file diff --git a/mission2/src/ProductService.js b/mission2/src/ProductService.js new file mode 100644 index 000000000..8d12141fe --- /dev/null +++ b/mission2/src/ProductService.js @@ -0,0 +1,89 @@ + export async function getProductList(params) { + const url = new URL(`https://panda-market-api-crud.vercel.app/products`); + Object.keys(params).forEach((key) => + url.searchParams.append(key, params[key]) + ); + + const res = await fetch(url); + const data = await res.json(); + return data; + } + + export async function getProduct() { + const res = await fetch (`https://panda-market-api-crud.vercel.app/products`); + const data = await res.json(); + return data; + } + + export async function createProduct(productData) { + const res = await fetch (`https://panda-market-api-crud.vercel.app/products`, { + method: 'POST', + body: JSON.stringify(productData), + headers: { + 'Content-Type': 'application/json', + }, + }); + + const data = await res.json(); + return data; + } + + export async function patchProduct(id, productData) { + const res = await fetch(`https://panda-market-api-crud.vercel.app/products/${id}`, { + method: 'PATCH', + body: JSON.stringify(productData), + headers: { + 'Content-Type': 'application/json' + }, + }); + const data = await res.json(); + return data; + } + + export async function deleteProduct(id) { + const res = await fetch(`https://panda-market-api-crud.vercel.app/products/${id}`, { + method: 'DELETE', + }); + const data = await res.json(); + return data; + } + + export async function checkProduct(id) { + const res = await fetch(`https://panda-market-api-crud.vercel.app/products/${id}`); + + if (!res.ok) { + throw new Error('데이터를 불러오는데 실패했습니다.'); + } + + const data = await res.json(); + return data; + } + + export async function createProducts(productData) { + let res; + try { + res = await fetch (`https://panda-market-api-crud.vercel.app/products`, { + method: 'POST', + body: JSON.stringify(productData), + headers: { + 'Content-Type': 'application/json', + }, + }); + } catch (error) { + console.error(error); + throw new Error('네트워크 전송 중 오류 발생'); + } + + if (!res.ok) { + throw new Error('네트워크 전송 중 오류 발생'); + } + + let data; + try { + data = await res.json(); + } catch (error) { + console.error(error); + throw new Error('JSON 피싱 중 오류 발생'); + } + return data; + } \ No newline at end of file diff --git a/mission2/src/README.md b/mission2/src/README.md new file mode 100644 index 000000000..bdcf03799 --- /dev/null +++ b/mission2/src/README.md @@ -0,0 +1,2 @@ +#Codeit Sprint mission collection +##Part 1 - sprint Mission 2 250722 \ No newline at end of file diff --git a/mission2/src/main.js b/mission2/src/main.js new file mode 100644 index 000000000..42ed7648e --- /dev/null +++ b/mission2/src/main.js @@ -0,0 +1,107 @@ +//Article --- + + import { getArticleList, getArticle, createArticle, patchArticle, deleteArticle } from "./ArticleService.js"; + + const data1 = await getArticleList('page', 'pageSize', 'keyword'); + console.log(data1); + + const data2 = await getArticle(); + console.log(data2); + + const articleData = { + title: '게시글 작성 테스트12345', + content: '게시글 작성 테스트입니다.', + image: 'https://example.com/...', + }; + + const data3 = await createArticle(articleData); + console.log(data3); + + +let article = await createArticle({ + title: '게시글 작성 테스트3', + content: '게시글 작성 테스트입니다.', + image: 'https://example.com/...', +}); + +console.log(article); + +article = await patchArticle(article.id, { + title: '게시글 작성 테테스트', + content: '게시글 작성 테스트중입니다.', + image: 'https://example.com/...', +}); + +console.log(article); +await deleteArticle(article.id); + +fetch(`https://panda-market-api-crud.vercel.app/docs/articles`) + .then((response) => response.json()) + .then((data) => console.log(data)) + .catch((error) => console.log('Error!')) + .finally(() => console.log('Finished')); + +async function getArticle() { + const response = await fetch(`https://panda-market-api-crud.vercel.app/articles`); + const data = await response.json(); + console.log(data); +}; + +fetch(`https://panda-market-api-crud.vercel.app/articles`) + .then((response) => response.json()) + .then((data) => console.log(data)); + +console.log('게시물을 불러내고 있습니다...'); + +//Product--- + +import { getProductList, getProduct, createProduct, patchProduct, deleteProduct, checkProduct } from "./ProductServicejs"; + +const data4 = await getProductList('page', 'pageSize', 'keyword'); +console.log(data4); + +const data5 = await getProduct(); +console.log(data5); + +const productData = { + name: '디지몬 피규어', + description: '가슴이 웅장해지는 오메가몬', + price: 80000, + tags: '장식', + images: "https://example.com/...", +}; + +const data6 = await createProduct(productData); +console.log(data6); + +let products = await createProduct({ + name: '디지몬 피규어', + description: '가슴이 웅장해지는 오메가몬', + price: 80000, + tags: '장식', + images: "https://example.com/...", +}); + +console.log(products); + +// const product = await patchProduct(id, { +// name: '디지털 몬스터', +// description: '어린 시절 모두가 했었던 다마고치', +// price: 40000, +// tags: '전자제품', +// images: "https://example.com/...", +// }); + +// console.log(product); + +// await deleteProduct(1258); + +import { checkProduct } from "./ProductService.js"; + +try { + const data = await checkProduct(id); + console.log(data); +} catch (e) { + console.log(`오류가 발생했습니다.`) + console.log(e.message); +} \ No newline at end of file From 1fee54e741dde2aa292d428c6c3aa8d9fcfc483a Mon Sep 17 00:00:00 2001 From: Batur-s Date: Wed, 23 Jul 2025 10:34:32 +0900 Subject: [PATCH 02/38] Update ArticleService.js --- mission2/src/ArticleService.js | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/mission2/src/ArticleService.js b/mission2/src/ArticleService.js index e9223fbea..1cc4e8849 100644 --- a/mission2/src/ArticleService.js +++ b/mission2/src/ArticleService.js @@ -1,3 +1,4 @@ +//getArticleList export async function getArticleList(params) { const url = new URL(`https://panda-market-api-crud.vercel.app/articles`); Object.keys(params).forEach((key) => @@ -9,12 +10,14 @@ export async function getArticleList(params) { return data; } +//getArticle export async function getArticle() { const res = await fetch (`https://panda-market-api-crud.vercel.app/articles`); const data = await res.json(); return data; } +//createArticle export async function createArticle(articleData) { const res = await fetch(`https://panda-market-api-crud.vercel.app/articles`, { method: 'POST', @@ -28,6 +31,7 @@ export async function createArticle(articleData) { return data; } +//patchArticle export async function patchArticle(id, articleData) { const res = await fetch(`https://panda-market-api-crud.vercel.app/articles/${id}`, { method: 'PATCH', @@ -40,6 +44,7 @@ export async function patchArticle(id, articleData) { return data; } +//deleteArticle export async function deleteArticle(id) { const res = await fetch(`https://panda-market-api-crud.vercel.app/articles/${id}`, { method: 'DELETE' @@ -47,17 +52,3 @@ export async function deleteArticle(id) { const data = await res.json(); return data; } - - import axios from 'axios'; - - axios.post(`https://panda-market-api-crud.vercel.app/articles`, { - title:'게시글 작성 테스트', - content: '게시글 작성 테스트', - image: 'https://example.com/...' - }) - .then(response => { - console.log('응답 데이터:', response.data); - }) - .catch(error => { - console.error('에러 발생:', error); - }); \ No newline at end of file From 5bb2a482f6147067114ae60b0520cf1e4aabcab9 Mon Sep 17 00:00:00 2001 From: Batur-s Date: Wed, 23 Jul 2025 10:35:20 +0900 Subject: [PATCH 03/38] Update Product.js --- mission2/src/Product.js | 42 ----------------------------------------- 1 file changed, 42 deletions(-) diff --git a/mission2/src/Product.js b/mission2/src/Product.js index ecaa95aa2..dcef2fc30 100644 --- a/mission2/src/Product.js +++ b/mission2/src/Product.js @@ -19,45 +19,3 @@ class ElectronicProduct extends Product{ this.manufacturer = manufacturer; } } - -import { getProductList, getProduct, createProduct, patchProduct } from "./ProductService.js"; - -function addNewProduct(products) { - const { name, description, price, tags, images, favoriteCount } = product; - const newProduct = { - id: products.length + 1, - name, - description, - price, - tags, - images, - favoriteCount, - }; - productsInput.push(newProduct); -} - -const productsInput = await getProduct(); - -console.log(productsInput); - -const products = productsInput; - -console.log(products); - -const electronicProduct = []; - -// productsInput.list.forEach((product) => { -// if(product.tags.find((element) => element === '전자제품')) { -// electronicProduct.push(product); -// } -// }); - -// console.log(electronicProduct); - -productsInput.list.forEach((product) => { - if(product.tags.includes('전자제품')) { - electronicProduct.push(product); - } -}); - -console.log(electronicProduct); \ No newline at end of file From 54e60694f97705e3212f2061fcfee2ee4e96a02f Mon Sep 17 00:00:00 2001 From: Batur-s Date: Wed, 23 Jul 2025 10:37:08 +0900 Subject: [PATCH 04/38] Update ProductService.js --- mission2/src/ProductService.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mission2/src/ProductService.js b/mission2/src/ProductService.js index 8d12141fe..689ee5f0a 100644 --- a/mission2/src/ProductService.js +++ b/mission2/src/ProductService.js @@ -1,3 +1,4 @@ + //getProductList export async function getProductList(params) { const url = new URL(`https://panda-market-api-crud.vercel.app/products`); Object.keys(params).forEach((key) => @@ -9,12 +10,14 @@ return data; } + //getProduct export async function getProduct() { const res = await fetch (`https://panda-market-api-crud.vercel.app/products`); const data = await res.json(); return data; } + //createProduct export async function createProduct(productData) { const res = await fetch (`https://panda-market-api-crud.vercel.app/products`, { method: 'POST', @@ -28,6 +31,7 @@ return data; } + //patchProduct export async function patchProduct(id, productData) { const res = await fetch(`https://panda-market-api-crud.vercel.app/products/${id}`, { method: 'PATCH', @@ -40,6 +44,7 @@ return data; } + //deleteProduct export async function deleteProduct(id) { const res = await fetch(`https://panda-market-api-crud.vercel.app/products/${id}`, { method: 'DELETE', @@ -48,6 +53,7 @@ return data; } + //비동기, 오류 처리 export async function checkProduct(id) { const res = await fetch(`https://panda-market-api-crud.vercel.app/products/${id}`); @@ -86,4 +92,4 @@ throw new Error('JSON 피싱 중 오류 발생'); } return data; - } \ No newline at end of file + } From 12e193a6b66d3cacef0800b3b3b8e33faab75e5d Mon Sep 17 00:00:00 2001 From: Batur-s Date: Wed, 23 Jul 2025 10:37:43 +0900 Subject: [PATCH 05/38] Update main.js --- mission2/src/main.js | 104 ++++++++++++++++++++++++++++++++----------- 1 file changed, 79 insertions(+), 25 deletions(-) diff --git a/mission2/src/main.js b/mission2/src/main.js index 42ed7648e..c3753d1b9 100644 --- a/mission2/src/main.js +++ b/mission2/src/main.js @@ -2,12 +2,15 @@ import { getArticleList, getArticle, createArticle, patchArticle, deleteArticle } from "./ArticleService.js"; + //getArticleList const data1 = await getArticleList('page', 'pageSize', 'keyword'); console.log(data1); + //getArticle const data2 = await getArticle(); console.log(data2); + //createArticle const articleData = { title: '게시글 작성 테스트12345', content: '게시글 작성 테스트입니다.', @@ -17,7 +20,7 @@ const data3 = await createArticle(articleData); console.log(data3); - +//patchArticle let article = await createArticle({ title: '게시글 작성 테스트3', content: '게시글 작성 테스트입니다.', @@ -33,36 +36,43 @@ article = await patchArticle(article.id, { }); console.log(article); + +//deleteArticle await deleteArticle(article.id); -fetch(`https://panda-market-api-crud.vercel.app/docs/articles`) - .then((response) => response.json()) - .then((data) => console.log(data)) - .catch((error) => console.log('Error!')) - .finally(() => console.log('Finished')); +// // 비동기 처리, 오류 처리 +// fetch(`https://panda-market-api-crud.vercel.app/docs/articles`) +// .then((response) => response.json()) +// .then((data) => console.log(data)) +// .catch((error) => console.log('Error!')) +// .finally(() => console.log('Finished')); -async function getArticle() { - const response = await fetch(`https://panda-market-api-crud.vercel.app/articles`); - const data = await response.json(); - console.log(data); -}; +// async function getArticle() { +// const response = await fetch(`https://panda-market-api-crud.vercel.app/articles`); +// const data = await response.json(); +// console.log(data); +// }; + +// fetch(`https://panda-market-api-crud.vercel.app/articles`) +// .then((response) => response.json()) +// .then((data) => console.log(data)); -fetch(`https://panda-market-api-crud.vercel.app/articles`) - .then((response) => response.json()) - .then((data) => console.log(data)); +// console.log('게시물을 불러내고 있습니다...'); -console.log('게시물을 불러내고 있습니다...'); //Product--- import { getProductList, getProduct, createProduct, patchProduct, deleteProduct, checkProduct } from "./ProductServicejs"; +//getProductList const data4 = await getProductList('page', 'pageSize', 'keyword'); console.log(data4); +//getProduct const data5 = await getProduct(); console.log(data5); +//createdProduct const productData = { name: '디지몬 피규어', description: '가슴이 웅장해지는 오메가몬', @@ -74,6 +84,7 @@ const productData = { const data6 = await createProduct(productData); console.log(data6); +//patchProduct let products = await createProduct({ name: '디지몬 피규어', description: '가슴이 웅장해지는 오메가몬', @@ -84,18 +95,20 @@ let products = await createProduct({ console.log(products); -// const product = await patchProduct(id, { -// name: '디지털 몬스터', -// description: '어린 시절 모두가 했었던 다마고치', -// price: 40000, -// tags: '전자제품', -// images: "https://example.com/...", -// }); +const product = await patchProduct(id, { + name: '디지털 몬스터', + description: '어린 시절 모두가 했었던 다마고치', + price: 40000, + tags: '전자제품', + images: "https://example.com/...", +}); -// console.log(product); +console.log(product); -// await deleteProduct(1258); +//deleteProduct +await deleteProduct(1258); +//비동기 처리, 오류 처리 import { checkProduct } from "./ProductService.js"; try { @@ -104,4 +117,45 @@ try { } catch (e) { console.log(`오류가 발생했습니다.`) console.log(e.message); -} \ No newline at end of file +} + +//해시태그 '전자제품' 분리 +function addNewProduct(products) { + const { name, description, price, tags, images, favoriteCount } = product; + const newProduct = { + id: products.length + 1, + name, + description, + price, + tags, + images, + favoriteCount, + }; + productsInput.push(newProduct); +} + +const productsInput = await getProduct(); + +console.log(productsInput); + +const products = productsInput; + +console.log(products); + +const electronicProduct = []; + +// productsInput.list.forEach((product) => { +// if(product.tags.find((element) => element === '전자제품')) { +// electronicProduct.push(product); +// } +// }); + +// console.log(electronicProduct); + +productsInput.list.forEach((product) => { + if(product.tags.includes('전자제품')) { + electronicProduct.push(product); + } +}); + +console.log(electronicProduct); From 88cd05c27b9f9d823af0ef5fbd524c7c8ab368de Mon Sep 17 00:00:00 2001 From: Batur-s Date: Thu, 24 Jul 2025 13:33:33 +0900 Subject: [PATCH 06/38] Update Article.js --- mission2/src/Article.js | 50 +++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/mission2/src/Article.js b/mission2/src/Article.js index eeda0fb08..0dce98378 100644 --- a/mission2/src/Article.js +++ b/mission2/src/Article.js @@ -1,13 +1,49 @@ -class Article { +export class Article { constructor(title, content, writer, likeCount ) { - this.title = title; - this.content = content; - this.writer = writer; - this.likeCount = likeCount; - this.createdAt = new Date(); + this._title = title; + this._content = content; + this._writer = writer; + this._likeCount = likeCount; + this._createdAt = new Date(); + } + + set title(input) { + this._title = input; + } + + set content(input) { + this._content = input; + } + + set writer(input) { + this._writer = input; + } + + set likeCount(input) { + this._likeCount = input; + } + + get title() { + return this._title; + } + + get content() { + return this._content; + } + + get writer() { + return this._writer; + } + + get likeCount() { + return this._likeCount; + } + + get createdAt() { + return this._createdAt; } like() { - likeCount ++; + this._likeCount ++; } } From d0f9143ac95966f8b0ee2ddbf4071f410d42dac4 Mon Sep 17 00:00:00 2001 From: Batur-s Date: Thu, 24 Jul 2025 13:34:00 +0900 Subject: [PATCH 07/38] Update Product.js --- mission2/src/Product.js | 56 +++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/mission2/src/Product.js b/mission2/src/Product.js index dcef2fc30..24cf34f67 100644 --- a/mission2/src/Product.js +++ b/mission2/src/Product.js @@ -1,21 +1,57 @@ -class Product { +export class Product { constructor(name, description, price, tags, images, favoriteCount) { - this.name = name; - this.description = description; - this.price = price; - this.tags = tags; - this.images = images; - this.favoriteCount = favoriteCount + this._name = name; + this._description = description; + this._price = price; + this._tags = tags; + this._images = images; + this._favoriteCount = favoriteCount + } + + set price(input) { + this._price = input; + } + + set tags(input) { + this._tags = input; + } + + set images(input) { + this._images = input; + } + + get price() { + return this._price; + } + + get tags() { + return this._tags; + } + + get images() { + return this._images; + } + + get favoriteCount() { + return this._favoriteCount; } favorite() { - favoriteCount ++; + this.favoriteCount ++; } } -class ElectronicProduct extends Product{ +export class ElectronicProduct extends Product{ constructor(name, description, price, tags, images, favoriteCount, manufacturer) { super(name, description, price, tags, images, favoriteCount); - this.manufacturer = manufacturer; + this._manufacturer = manufacturer; + } + + set manufacturer(input) { + this._manufacturer = input; + } + + get manufacturer() { + return this._manufacturer; } } From 98ed02347887f835d75ce0b7c854924aeedff03d Mon Sep 17 00:00:00 2001 From: baturs Date: Tue, 5 Aug 2025 17:09:47 +0900 Subject: [PATCH 08/38] modified files --- mission2/src/Article.js | 50 +++++++++++-- mission2/src/ArticleService.js | 21 ++---- mission2/src/Product.js | 90 +++++++++++------------ mission2/src/ProductService.js | 6 ++ mission2/src/main.js | 130 +++++++++++++++++++++++---------- 5 files changed, 189 insertions(+), 108 deletions(-) diff --git a/mission2/src/Article.js b/mission2/src/Article.js index eeda0fb08..0dce98378 100644 --- a/mission2/src/Article.js +++ b/mission2/src/Article.js @@ -1,13 +1,49 @@ -class Article { +export class Article { constructor(title, content, writer, likeCount ) { - this.title = title; - this.content = content; - this.writer = writer; - this.likeCount = likeCount; - this.createdAt = new Date(); + this._title = title; + this._content = content; + this._writer = writer; + this._likeCount = likeCount; + this._createdAt = new Date(); + } + + set title(input) { + this._title = input; + } + + set content(input) { + this._content = input; + } + + set writer(input) { + this._writer = input; + } + + set likeCount(input) { + this._likeCount = input; + } + + get title() { + return this._title; + } + + get content() { + return this._content; + } + + get writer() { + return this._writer; + } + + get likeCount() { + return this._likeCount; + } + + get createdAt() { + return this._createdAt; } like() { - likeCount ++; + this._likeCount ++; } } diff --git a/mission2/src/ArticleService.js b/mission2/src/ArticleService.js index e9223fbea..948cfc30f 100644 --- a/mission2/src/ArticleService.js +++ b/mission2/src/ArticleService.js @@ -1,3 +1,4 @@ +//getArticleList export async function getArticleList(params) { const url = new URL(`https://panda-market-api-crud.vercel.app/articles`); Object.keys(params).forEach((key) => @@ -9,12 +10,14 @@ export async function getArticleList(params) { return data; } +//getArticle export async function getArticle() { const res = await fetch (`https://panda-market-api-crud.vercel.app/articles`); const data = await res.json(); return data; } +//createArticle export async function createArticle(articleData) { const res = await fetch(`https://panda-market-api-crud.vercel.app/articles`, { method: 'POST', @@ -28,6 +31,7 @@ export async function createArticle(articleData) { return data; } +//patchArticle export async function patchArticle(id, articleData) { const res = await fetch(`https://panda-market-api-crud.vercel.app/articles/${id}`, { method: 'PATCH', @@ -40,24 +44,11 @@ export async function patchArticle(id, articleData) { return data; } +//deleteArticle export async function deleteArticle(id) { const res = await fetch(`https://panda-market-api-crud.vercel.app/articles/${id}`, { method: 'DELETE' }); const data = await res.json(); return data; -} - - import axios from 'axios'; - - axios.post(`https://panda-market-api-crud.vercel.app/articles`, { - title:'게시글 작성 테스트', - content: '게시글 작성 테스트', - image: 'https://example.com/...' - }) - .then(response => { - console.log('응답 데이터:', response.data); - }) - .catch(error => { - console.error('에러 발생:', error); - }); \ No newline at end of file +} \ No newline at end of file diff --git a/mission2/src/Product.js b/mission2/src/Product.js index ecaa95aa2..84980739d 100644 --- a/mission2/src/Product.js +++ b/mission2/src/Product.js @@ -1,63 +1,57 @@ -class Product { +export class Product { constructor(name, description, price, tags, images, favoriteCount) { - this.name = name; - this.description = description; - this.price = price; - this.tags = tags; - this.images = images; - this.favoriteCount = favoriteCount + this._name = name; + this._description = description; + this._price = price; + this._tags = tags; + this._images = images; + this._favoriteCount = favoriteCount } - favorite() { - favoriteCount ++; + set price(input) { + this._price = input; } -} -class ElectronicProduct extends Product{ - constructor(name, description, price, tags, images, favoriteCount, manufacturer) { - super(name, description, price, tags, images, favoriteCount); - this.manufacturer = manufacturer; + set tags(input) { + this._tags = input; } -} -import { getProductList, getProduct, createProduct, patchProduct } from "./ProductService.js"; - -function addNewProduct(products) { - const { name, description, price, tags, images, favoriteCount } = product; - const newProduct = { - id: products.length + 1, - name, - description, - price, - tags, - images, - favoriteCount, - }; - productsInput.push(newProduct); -} - -const productsInput = await getProduct(); - -console.log(productsInput); + set images(input) { + this._images = input; + } -const products = productsInput; + get price() { + return this._price; + } + + get tags() { + return this._tags; + } -console.log(products); + get images() { + return this._images; + } -const electronicProduct = []; + get favoriteCount() { + return this._favoriteCount; + } -// productsInput.list.forEach((product) => { -// if(product.tags.find((element) => element === '전자제품')) { -// electronicProduct.push(product); -// } -// }); + favorite() { + this.favoriteCount ++; + } +} -// console.log(electronicProduct); +export class ElectronicProduct extends Product{ + constructor(name, description, price, tags, images, favoriteCount, manufacturer) { + super(name, description, price, tags, images, favoriteCount); + this._manufacturer = manufacturer; + } -productsInput.list.forEach((product) => { - if(product.tags.includes('전자제품')) { - electronicProduct.push(product); + set manufacturer(input) { + this._manufacturer = input; } -}); -console.log(electronicProduct); \ No newline at end of file + get manufacturer() { + return this._manufacturer; + } +} \ No newline at end of file diff --git a/mission2/src/ProductService.js b/mission2/src/ProductService.js index 8d12141fe..5c374ec63 100644 --- a/mission2/src/ProductService.js +++ b/mission2/src/ProductService.js @@ -1,3 +1,4 @@ + //getProductList export async function getProductList(params) { const url = new URL(`https://panda-market-api-crud.vercel.app/products`); Object.keys(params).forEach((key) => @@ -9,12 +10,14 @@ return data; } + //getProduct export async function getProduct() { const res = await fetch (`https://panda-market-api-crud.vercel.app/products`); const data = await res.json(); return data; } + //createProduct export async function createProduct(productData) { const res = await fetch (`https://panda-market-api-crud.vercel.app/products`, { method: 'POST', @@ -28,6 +31,7 @@ return data; } + //patchProduct export async function patchProduct(id, productData) { const res = await fetch(`https://panda-market-api-crud.vercel.app/products/${id}`, { method: 'PATCH', @@ -40,6 +44,7 @@ return data; } + //deleteProduct export async function deleteProduct(id) { const res = await fetch(`https://panda-market-api-crud.vercel.app/products/${id}`, { method: 'DELETE', @@ -48,6 +53,7 @@ return data; } + //비동기, 오류 처리 export async function checkProduct(id) { const res = await fetch(`https://panda-market-api-crud.vercel.app/products/${id}`); diff --git a/mission2/src/main.js b/mission2/src/main.js index 42ed7648e..a8ae65047 100644 --- a/mission2/src/main.js +++ b/mission2/src/main.js @@ -1,13 +1,16 @@ //Article --- - import { getArticleList, getArticle, createArticle, patchArticle, deleteArticle } from "./ArticleService.js"; + import { getArticleList, getArticle, createArticle, patchArticle, deleteArticle } from './ArticleService.js'; + //getArticleList const data1 = await getArticleList('page', 'pageSize', 'keyword'); console.log(data1); + //getArticle const data2 = await getArticle(); console.log(data2); + //createArticle const articleData = { title: '게시글 작성 테스트12345', content: '게시글 작성 테스트입니다.', @@ -17,7 +20,7 @@ const data3 = await createArticle(articleData); console.log(data3); - +//patchArticle let article = await createArticle({ title: '게시글 작성 테스트3', content: '게시글 작성 테스트입니다.', @@ -33,19 +36,22 @@ article = await patchArticle(article.id, { }); console.log(article); + +//deleteArticle await deleteArticle(article.id); +// 비동기 처리, 오류 처리 fetch(`https://panda-market-api-crud.vercel.app/docs/articles`) .then((response) => response.json()) .then((data) => console.log(data)) .catch((error) => console.log('Error!')) .finally(() => console.log('Finished')); -async function getArticle() { - const response = await fetch(`https://panda-market-api-crud.vercel.app/articles`); - const data = await response.json(); - console.log(data); -}; +// async function getArticle() { +// const response = await fetch(`https://panda-market-api-crud.vercel.app/articles`); +// const data = await response.json(); +// console.log(nodpe data); +// }; fetch(`https://panda-market-api-crud.vercel.app/articles`) .then((response) => response.json()) @@ -53,36 +59,41 @@ fetch(`https://panda-market-api-crud.vercel.app/articles`) console.log('게시물을 불러내고 있습니다...'); -//Product--- -import { getProductList, getProduct, createProduct, patchProduct, deleteProduct, checkProduct } from "./ProductServicejs"; +// //Product--- -const data4 = await getProductList('page', 'pageSize', 'keyword'); -console.log(data4); +// import { getProductList, getProduct, createProduct, patchProduct, deleteProduct, checkProduct } from "./ProductServicejs"; -const data5 = await getProduct(); -console.log(data5); +// //getProductList +// const data4 = await getProductList('page', 'pageSize', 'keyword'); +// console.log(data4); -const productData = { - name: '디지몬 피규어', - description: '가슴이 웅장해지는 오메가몬', - price: 80000, - tags: '장식', - images: "https://example.com/...", -}; +// //getProduct +// const data5 = await getProduct(); +// console.log(data5); -const data6 = await createProduct(productData); -console.log(data6); +// //createdProduct +// const productData = { +// name: '디지몬 피규어', +// description: '가슴이 웅장해지는 오메가몬', +// price: 80000, +// tags: '장식', +// images: "https://example.com/...", +// }; -let products = await createProduct({ - name: '디지몬 피규어', - description: '가슴이 웅장해지는 오메가몬', - price: 80000, - tags: '장식', - images: "https://example.com/...", -}); +// const data6 = await createProduct(productData); +// console.log(data6); -console.log(products); +// //patchProduct +// let products = await createProduct({ +// name: '디지몬 피규어', +// description: '가슴이 웅장해지는 오메가몬', +// price: 80000, +// tags: '장식', +// images: "https://example.com/...", +// }); + +// console.log(products); // const product = await patchProduct(id, { // name: '디지털 몬스터', @@ -94,14 +105,57 @@ console.log(products); // console.log(product); +// //deleteProduct // await deleteProduct(1258); -import { checkProduct } from "./ProductService.js"; +// //비동기 처리, 오류 처리 +// import { checkProduct } from "./ProductService.js"; + +// try { +// const data = await checkProduct(id); +// console.log(data); +// } catch (e) { +// console.log(`오류가 발생했습니다.`) +// console.log(e.message); +// } + +// //해시태그 '전자제품' 분리 +// function addNewProduct(products) { +// const { name, description, price, tags, images, favoriteCount } = product; +// const newProduct = { +// id: products.length + 1, +// name, +// description, +// price, +// tags, +// images, +// favoriteCount, +// }; +// productsInput.push(newProduct); +// } + +// const productsInput = await getProduct(); + +// console.log(productsInput); + +// const products = productsInput; + +// console.log(products); + +// const electronicProduct = []; + +// // productsInput.list.forEach((product) => { +// // if(product.tags.find((element) => element === '전자제품')) { +// // electronicProduct.push(product); +// // } +// // }); + +// // console.log(electronicProduct); + +// productsInput.list.forEach((product) => { +// if(product.tags.includes('전자제품')) { +// electronicProduct.push(product); +// } +// }); -try { - const data = await checkProduct(id); - console.log(data); -} catch (e) { - console.log(`오류가 발생했습니다.`) - console.log(e.message); -} \ No newline at end of file +// console.log(electronicProduct); \ No newline at end of file From 17d740c235878578608326fb37b590f9268d21bd Mon Sep 17 00:00:00 2001 From: baturs Date: Thu, 7 Aug 2025 17:36:22 +0900 Subject: [PATCH 09/38] modified files3 --- mission3 | 1 + 1 file changed, 1 insertion(+) create mode 160000 mission3 diff --git a/mission3 b/mission3 new file mode 160000 index 000000000..f58d986af --- /dev/null +++ b/mission3 @@ -0,0 +1 @@ +Subproject commit f58d986af29267df4058ab92895a921c39a432b0 From 414c28fd12f649ee9ba9f50b0c609642717e1c36 Mon Sep 17 00:00:00 2001 From: baturs Date: Thu, 7 Aug 2025 17:47:40 +0900 Subject: [PATCH 10/38] Revert "modified files3" This reverts commit 17d740c235878578608326fb37b590f9268d21bd. --- mission3 | 1 - 1 file changed, 1 deletion(-) delete mode 160000 mission3 diff --git a/mission3 b/mission3 deleted file mode 160000 index f58d986af..000000000 --- a/mission3 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f58d986af29267df4058ab92895a921c39a432b0 From 6a72b62293f9f9d99347cdbd6a624d00bc1123b9 Mon Sep 17 00:00:00 2001 From: baturs Date: Thu, 7 Aug 2025 18:07:50 +0900 Subject: [PATCH 11/38] finally commit in today --- mission3 | 1 + 1 file changed, 1 insertion(+) create mode 160000 mission3 diff --git a/mission3 b/mission3 new file mode 160000 index 000000000..d75bcf31c --- /dev/null +++ b/mission3 @@ -0,0 +1 @@ +Subproject commit d75bcf31c3e111890d07eabb1e089e6e9cfe3959 From e50fea22958a520c9e6edca271d8fbf85398668c Mon Sep 17 00:00:00 2001 From: baturs Date: Fri, 8 Aug 2025 09:23:08 +0900 Subject: [PATCH 12/38] Revert "finally commit in today" This reverts commit 6a72b62293f9f9d99347cdbd6a624d00bc1123b9. --- mission3 | 1 - 1 file changed, 1 deletion(-) delete mode 160000 mission3 diff --git a/mission3 b/mission3 deleted file mode 160000 index d75bcf31c..000000000 --- a/mission3 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d75bcf31c3e111890d07eabb1e089e6e9cfe3959 From 5171470d8839d717f3079a321551280ed775a4fd Mon Sep 17 00:00:00 2001 From: baturs Date: Fri, 8 Aug 2025 09:26:51 +0900 Subject: [PATCH 13/38] recommit --- mission3/.env | 11 + mission3/.gitignore | 4 + mission3/package-lock.json | 1689 +++++++++++++++++ mission3/package.json | 25 + .../20250801040813_test1/migration.sql | 12 + .../migrations/20250801043117_/migration.sql | 13 + .../migrations/20250801052248_/migration.sql | 2 + .../migrations/20250801054312_/migration.sql | 8 + .../migrations/20250801084111_/migration.sql | 12 + .../migrations/20250804015022_/migration.sql | 16 + .../migrations/20250804071412_/migration.sql | 8 + .../migrations/20250806024208_/migration.sql | 11 + .../migrations/20250806075011_/migration.sql | 3 + .../prisma/migrations/migration_lock.toml | 3 + mission3/prisma/schema.prisma | 38 + mission3/prisma/seed.js | 23 + mission3/src/app.js | 47 + mission3/src/router/articleRouter.js | 129 ++ mission3/src/router/commentRouter.js | 155 ++ mission3/src/router/productRouter.js | 140 ++ 20 files changed, 2349 insertions(+) create mode 100644 mission3/.env create mode 100644 mission3/.gitignore create mode 100644 mission3/package-lock.json create mode 100644 mission3/package.json create mode 100644 mission3/prisma/migrations/20250801040813_test1/migration.sql create mode 100644 mission3/prisma/migrations/20250801043117_/migration.sql create mode 100644 mission3/prisma/migrations/20250801052248_/migration.sql create mode 100644 mission3/prisma/migrations/20250801054312_/migration.sql create mode 100644 mission3/prisma/migrations/20250801084111_/migration.sql create mode 100644 mission3/prisma/migrations/20250804015022_/migration.sql create mode 100644 mission3/prisma/migrations/20250804071412_/migration.sql create mode 100644 mission3/prisma/migrations/20250806024208_/migration.sql create mode 100644 mission3/prisma/migrations/20250806075011_/migration.sql create mode 100644 mission3/prisma/migrations/migration_lock.toml create mode 100644 mission3/prisma/schema.prisma create mode 100644 mission3/prisma/seed.js create mode 100644 mission3/src/app.js create mode 100644 mission3/src/router/articleRouter.js create mode 100644 mission3/src/router/commentRouter.js create mode 100644 mission3/src/router/productRouter.js diff --git a/mission3/.env b/mission3/.env new file mode 100644 index 000000000..81a5c5853 --- /dev/null +++ b/mission3/.env @@ -0,0 +1,11 @@ +# Environment variables declared in this file are automatically made available to Prisma. +# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema + +# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. +# See the documentation for all the connection string options: https://pris.ly/d/connection-strings + +# The following `prisma+postgres` URL is similar to the URL produced by running a local Prisma Postgres +# server with the `prisma dev` CLI command, when not choosing any non-default ports or settings. The API key, unlike the +# one found in a remote Prisma Postgres URL, does not contain any sensitive information. + +DATABASE_URL="postgresql://baturs:wlqkrtls5@localhost:5432/test_db?schema=public" \ No newline at end of file diff --git a/mission3/.gitignore b/mission3/.gitignore new file mode 100644 index 000000000..fdae56f2e --- /dev/null +++ b/mission3/.gitignore @@ -0,0 +1,4 @@ +node_modules +# Keep environment variables out of version control + +/generated/prisma diff --git a/mission3/package-lock.json b/mission3/package-lock.json new file mode 100644 index 000000000..5ffb28de2 --- /dev/null +++ b/mission3/package-lock.json @@ -0,0 +1,1689 @@ +{ + "name": "mission3", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mission3", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@prisma/client": "^6.13.0", + "cors": "^2.8.5", + "express": "^5.1.0", + "multer": "^2.0.2", + "zod": "^4.0.14" + }, + "devDependencies": { + "prisma": "^6.13.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@prisma/client": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.13.0.tgz", + "integrity": "sha512-8m2+I3dQovkV8CkDMluiwEV1TxV9EXdT6xaCz39O6jYw7mkf5gwfmi+cL4LJsEPwz5tG7sreBwkRpEMJedGYUQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "prisma": "*", + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@prisma/config": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.13.0.tgz", + "integrity": "sha512-OYMM+pcrvj/NqNWCGESSxVG3O7kX6oWuGyvufTUNnDw740KIQvNyA4v0eILgkpuwsKIDU36beZCkUtIt0naTog==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "c12": "3.1.0", + "deepmerge-ts": "7.1.5", + "effect": "3.16.12", + "read-package-up": "11.0.0" + } + }, + "node_modules/@prisma/debug": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.13.0.tgz", + "integrity": "sha512-um+9pfKJW0ihmM83id9FXGi5qEbVJ0Vxi1Gm0xpYsjwUBnw6s2LdPBbrsG9QXRX46K4CLWCTNvskXBup4i9hlw==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.13.0.tgz", + "integrity": "sha512-D+1B79LFvtWA0KTt8ALekQ6A/glB9w10ETknH5Y9g1k2NYYQOQy93ffiuqLn3Pl6IPJG3EsK/YMROKEaq8KBrA==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.13.0", + "@prisma/engines-version": "6.13.0-35.361e86d0ea4987e9f53a565309b3eed797a6bcbd", + "@prisma/fetch-engine": "6.13.0", + "@prisma/get-platform": "6.13.0" + } + }, + "node_modules/@prisma/engines-version": { + "version": "6.13.0-35.361e86d0ea4987e9f53a565309b3eed797a6bcbd", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.13.0-35.361e86d0ea4987e9f53a565309b3eed797a6bcbd.tgz", + "integrity": "sha512-MpPyKSzBX7P/ZY9odp9TSegnS/yH3CSbchQE9f0yBg3l2QyN59I6vGXcoYcqKC9VTniS1s18AMmhyr1OWavjHg==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.13.0.tgz", + "integrity": "sha512-grmmq+4FeFKmaaytA8Ozc2+Tf3BC8xn/DVJos6LL022mfRlMZYjT3hZM0/xG7+5fO95zFG9CkDUs0m1S2rXs5Q==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.13.0", + "@prisma/engines-version": "6.13.0-35.361e86d0ea4987e9f53a565309b3eed797a6bcbd", + "@prisma/get-platform": "6.13.0" + } + }, + "node_modules/@prisma/get-platform": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.13.0.tgz", + "integrity": "sha512-Nii2pX50fY4QKKxQwm7/vvqT6Ku8yYJLZAFX4e2vzHwRdMqjugcOG5hOSLjxqoXb0cvOspV70TOhMzrw8kqAnw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.13.0" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/c12": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", + "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.3", + "confbox": "^0.2.2", + "defu": "^6.1.4", + "dotenv": "^16.6.1", + "exsolve": "^1.0.7", + "giget": "^2.0.0", + "jiti": "^2.4.2", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^1.0.0", + "pkg-types": "^2.2.0", + "rc9": "^2.1.2" + }, + "peerDependencies": { + "magicast": "^0.3.5" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "consola": "^3.2.3" + } + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deepmerge-ts": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", + "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "devOptional": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/effect": { + "version": "3.16.12", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.16.12.tgz", + "integrity": "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "fast-check": "^3.23.1" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/fast-check": { + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", + "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "dependencies": { + "pure-rand": "^6.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/giget": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", + "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.0", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.6", + "nypm": "^0.6.0", + "pathe": "^2.0.3" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/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==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/index-to-position": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.1.0.tgz", + "integrity": "sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/jiti": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", + "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "devOptional": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "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==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/multer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", + "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", + "object-assign": "^4.1.1", + "type-is": "^1.6.18", + "xtend": "^4.0.2" + }, + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/multer/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.6.tgz", + "integrity": "sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "devOptional": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/nypm": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.1.tgz", + "integrity": "sha512-hlacBiRiv1k9hZFiphPUkfSQ/ZfQzZDzC+8z0wL3lvDAOUu/2NnChkKuMoMjNur/9OpKuz2QsIeiPVN0xM5Q0w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.2", + "pathe": "^2.0.3", + "pkg-types": "^2.2.0", + "tinyexec": "^1.0.1" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "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==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + }, + "engines": { + "node": ">=18" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/pkg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.2.0.tgz", + "integrity": "sha512-2SM/GZGAEkPp3KWORxQZns4M+WSeXbC2HEvmOIJe3Cmiv6ieAJvdVhDldtHqM5J1Y7MrR1XhkBT/rMlhh9FdqQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, + "node_modules/prisma": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.13.0.tgz", + "integrity": "sha512-dfzORf0AbcEyyzxuv2lEwG8g+WRGF/qDQTpHf/6JoHsyF5MyzCEZwClVaEmw3WXcobgadosOboKUgQU0kFs9kw==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/config": "6.13.0", + "@prisma/engines": "6.13.0" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc9": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", + "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "defu": "^6.1.4", + "destr": "^2.0.3" + } + }, + "node_modules/read-package-up": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz", + "integrity": "sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "find-up-simple": "^1.0.0", + "read-pkg": "^9.0.0", + "type-fest": "^4.6.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", + "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "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" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "devOptional": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "devOptional": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.21", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", + "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", + "devOptional": true, + "license": "CC0-1.0" + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/tinyexec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "devOptional": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "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==", + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/zod": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.0.14.tgz", + "integrity": "sha512-nGFJTnJN6cM2v9kXL+SOBq3AtjQby3Mv5ySGFof5UGRHrRioSJ5iG680cYNjE/yWk671nROcpPj4hAS8nyLhSw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/mission3/package.json b/mission3/package.json new file mode 100644 index 000000000..adacf9860 --- /dev/null +++ b/mission3/package.json @@ -0,0 +1,25 @@ +{ + "name": "mission3", + "version": "1.0.0", + "main": "index.js", + "type": "module", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "@prisma/client": "^6.13.0", + "cors": "^2.8.5", + "express": "^5.1.0", + "multer": "^2.0.2", + "zod": "^4.0.14" + }, + "devDependencies": { + "prisma": "^6.13.0" + }, + "prisma": { + "seed": "node prisma/seed.js" + } +} diff --git a/mission3/prisma/migrations/20250801040813_test1/migration.sql b/mission3/prisma/migrations/20250801040813_test1/migration.sql new file mode 100644 index 000000000..e2428e60a --- /dev/null +++ b/mission3/prisma/migrations/20250801040813_test1/migration.sql @@ -0,0 +1,12 @@ +-- CreateTable +CREATE TABLE "public"."Product" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "price" INTEGER NOT NULL, + "tags" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Product_pkey" PRIMARY KEY ("id") +); diff --git a/mission3/prisma/migrations/20250801043117_/migration.sql b/mission3/prisma/migrations/20250801043117_/migration.sql new file mode 100644 index 000000000..0bc93e1a6 --- /dev/null +++ b/mission3/prisma/migrations/20250801043117_/migration.sql @@ -0,0 +1,13 @@ +-- CreateTable +CREATE TABLE "public"."Article" ( + "id" SERIAL NOT NULL, + "title" TEXT NOT NULL, + "content" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Article_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "Article_title_key" ON "public"."Article"("title"); diff --git a/mission3/prisma/migrations/20250801052248_/migration.sql b/mission3/prisma/migrations/20250801052248_/migration.sql new file mode 100644 index 000000000..e7f517914 --- /dev/null +++ b/mission3/prisma/migrations/20250801052248_/migration.sql @@ -0,0 +1,2 @@ +-- DropIndex +DROP INDEX "public"."Article_title_key"; diff --git a/mission3/prisma/migrations/20250801054312_/migration.sql b/mission3/prisma/migrations/20250801054312_/migration.sql new file mode 100644 index 000000000..006933c78 --- /dev/null +++ b/mission3/prisma/migrations/20250801054312_/migration.sql @@ -0,0 +1,8 @@ +-- CreateTable +CREATE TABLE "public"."comment" ( + "id" SERIAL NOT NULL, + "content" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "comment_pkey" PRIMARY KEY ("id") +); diff --git a/mission3/prisma/migrations/20250801084111_/migration.sql b/mission3/prisma/migrations/20250801084111_/migration.sql new file mode 100644 index 000000000..21689cf61 --- /dev/null +++ b/mission3/prisma/migrations/20250801084111_/migration.sql @@ -0,0 +1,12 @@ +/* + Warnings: + + - You are about to drop the `comment` table. If the table is not empty, all the data it contains will be lost. + - Made the column `content` on table `Article` required. This step will fail if there are existing NULL values in that column. + +*/ +-- AlterTable +ALTER TABLE "public"."Article" ALTER COLUMN "content" SET NOT NULL; + +-- DropTable +DROP TABLE "public"."comment"; diff --git a/mission3/prisma/migrations/20250804015022_/migration.sql b/mission3/prisma/migrations/20250804015022_/migration.sql new file mode 100644 index 000000000..1aa312424 --- /dev/null +++ b/mission3/prisma/migrations/20250804015022_/migration.sql @@ -0,0 +1,16 @@ +-- CreateTable +CREATE TABLE "public"."Comment" ( + "id" SERIAL NOT NULL, + "content" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "productId" INTEGER NOT NULL, + "articleId" INTEGER NOT NULL, + + CONSTRAINT "Comment_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_productId_fkey" FOREIGN KEY ("productId") REFERENCES "public"."Product"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "public"."Article"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/mission3/prisma/migrations/20250804071412_/migration.sql b/mission3/prisma/migrations/20250804071412_/migration.sql new file mode 100644 index 000000000..529f4b90f --- /dev/null +++ b/mission3/prisma/migrations/20250804071412_/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - Made the column `description` on table `Product` required. This step will fail if there are existing NULL values in that column. + +*/ +-- AlterTable +ALTER TABLE "public"."Product" ALTER COLUMN "description" SET NOT NULL; diff --git a/mission3/prisma/migrations/20250806024208_/migration.sql b/mission3/prisma/migrations/20250806024208_/migration.sql new file mode 100644 index 000000000..5b2790f30 --- /dev/null +++ b/mission3/prisma/migrations/20250806024208_/migration.sql @@ -0,0 +1,11 @@ +-- DropForeignKey +ALTER TABLE "public"."Comment" DROP CONSTRAINT "Comment_articleId_fkey"; + +-- DropForeignKey +ALTER TABLE "public"."Comment" DROP CONSTRAINT "Comment_productId_fkey"; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_productId_fkey" FOREIGN KEY ("productId") REFERENCES "public"."Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "public"."Article"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/mission3/prisma/migrations/20250806075011_/migration.sql b/mission3/prisma/migrations/20250806075011_/migration.sql new file mode 100644 index 000000000..91d7bd16b --- /dev/null +++ b/mission3/prisma/migrations/20250806075011_/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE "public"."Comment" ALTER COLUMN "productId" DROP NOT NULL, +ALTER COLUMN "articleId" DROP NOT NULL; diff --git a/mission3/prisma/migrations/migration_lock.toml b/mission3/prisma/migrations/migration_lock.toml new file mode 100644 index 000000000..044d57cdb --- /dev/null +++ b/mission3/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (e.g., Git) +provider = "postgresql" diff --git a/mission3/prisma/schema.prisma b/mission3/prisma/schema.prisma new file mode 100644 index 000000000..579fb51df --- /dev/null +++ b/mission3/prisma/schema.prisma @@ -0,0 +1,38 @@ +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" +} + +model Product { + id Int @id @default(autoincrement()) + name String + description String + price Int + tags String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + comment Comment[] +} + +model Article { + id Int @id @default(autoincrement()) + title String + content String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + comment Comment[] +} + +model Comment { + id Int @id @default(autoincrement()) + content String + createdAt DateTime @default(now()) + productId Int? + product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) + articleId Int? + article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) +} \ No newline at end of file diff --git a/mission3/prisma/seed.js b/mission3/prisma/seed.js new file mode 100644 index 000000000..fc0affadc --- /dev/null +++ b/mission3/prisma/seed.js @@ -0,0 +1,23 @@ +import { PrismaClient } from '@prisma/client'; + +const prisma = new PrismaClient(); + +const main = async () => { + await prisma.product.create({ + data: { + name: '디지몬피규어', + description: '가슴이 웅장해지는 오메가몬과 디아블로몬의 전투장면의 표현한 피규어', + price: 80000, + tags: '장식', + }, + }); + await prisma.article.create({ + data: { + title: 'Article test', + content: 'Article 테스트 글입니다.', + }, + }); +}; + + +main().then(() => prisma.$disconnect()); \ No newline at end of file diff --git a/mission3/src/app.js b/mission3/src/app.js new file mode 100644 index 000000000..6ea45c5be --- /dev/null +++ b/mission3/src/app.js @@ -0,0 +1,47 @@ +import express from 'express'; +import multer from 'multer'; +import cors from 'cors'; +import { PrismaClient } from '@prisma/client'; +import productRouter from './router/productRouter.js'; +import articleRouter from './router/articleRouter.js'; +import commentRouter from './router/commentRouter.js'; + +const router = express.Router(); + +const app = express(); + +const prisma = new PrismaClient(); + +app.use(express.urlencoded({ extended: true })); + +app.use(express.json()); + +app.use('/products', productRouter); +app.use('/articles', articleRouter); +app.use('/comments', commentRouter); + +const upload = multer({ dest: 'uploads/'}) + +app.post('/photos', upload.single('image'), (req, res) => { + const path = 'download/' + req.file.filename; + res.json({ path }); +}); + +app.use('/downlaod', express.static('uploads')); + +const corsOptions = { + origin: 'http://localhost:3000', + optionSuccessStatus: 200 +} + +app.use(cors(corsOptions)); + +// app.use((err, res, res, next) => { +// console.error(err.stack); +// res.status(500).send('Something broke!'); +// }); + +const port = 3000; +app.listen(port, () => { + console.log(`Server is running on http://localhost:${port}`); +}); diff --git a/mission3/src/router/articleRouter.js b/mission3/src/router/articleRouter.js new file mode 100644 index 000000000..e80a68771 --- /dev/null +++ b/mission3/src/router/articleRouter.js @@ -0,0 +1,129 @@ +import { PrismaClient } from '@prisma/client'; +import express from 'express'; +import z from 'zod'; + +const articleRouter = express.Router(); + +const prisma = new PrismaClient(); + +const createArticleSchema = z.object({ + title: z.string().min(1, { message: "제목을 입력해주세요" }), + content: z.string().min(30, { message: "내용은 최소 30자 이상이어야 합니다." }).max(200, { message: "내용은 최대 200자까지 가능합니다." }), +}); + +articleRouter.route('/') //Article 등록하기 + .post(async(req, res) => { + try { + const validatedData = createArticleSchema.parse(req.body); + } catch (err) { + res.status(404).json({ error: msg.error }); + }; + const { title, content } = validatedData; + + try { + const article = await prisma.article.create({ + data: { + title, + content, + }, + }); + res.json({ message: 'Complete to post your article!' }); + } catch (err) { + res.status(500).json({ error: 'Article is not posted' }); + } +}) + + .get(async(req, res) => { //검색어로 Article 조회 및 전체 Article 조회 + try { + const page = parseInt(req.query.page); + const keyword = req.query.keyword; + const where = keyword + ? { + OR: [ + { + name: { + contains: keyword, + }, + }, + { + description: { + contains: keyword, + }, + }, + ], + } + : undefined; + + const articles = await prisma.article.findMany({ + skip: (page - 1) * 5, + take: 5, + orderBy: { + createdAt: 'asc', + }, + select: { + id: true, + title: true, + content: true, + createdAt: true, + }, + where + }); + res.status(201).json(articles); + } catch (error) { + console.error(error); + res.status(404).json({ error: `Can't find articles`}) + } + }); + +articleRouter.route('/:id') + .patch(async(req, res) => { //id를 통해 Article 수정하기 + const articleId = Number(req.params.id); + const { title, content } = req.body; + + try { + const updated = await prisma.article.update({ + where: { id: articleId }, + data: { + title, + content, + }, + }); + res.status(201).json(updated); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}) + + .delete(async(req, res) => { //id통해서 Article 삭제하기 + const articleId = Number(req.params.id); + + try { + await prisma.article.delete({ + wehre: { id: articleId }, + }); + res.json({ message: 'Article is deleted' }); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}) + + .get(async(req, res) => { //id를 통해서 Article 조회하기 + const articleId = Number(req.params.id); + + try { + const article = await prisma.product.findUnique({ + where: { id: articleId }, + select: { + id: true, + title: true, + content: true, + createdAt: true, + }, + }); + res.status(201).json(article); + } catch (err) { + res.status(404).json({ error: `Can't find article`}) + } + }); + +export default articleRouter; diff --git a/mission3/src/router/commentRouter.js b/mission3/src/router/commentRouter.js new file mode 100644 index 000000000..4b57e666e --- /dev/null +++ b/mission3/src/router/commentRouter.js @@ -0,0 +1,155 @@ +import { PrismaClient } from '@prisma/client'; +import express from 'express'; +import { string } from 'zod'; + +const commentRouter = express.Router(); + +const prisma = new PrismaClient(); + +commentRouter.route('/') + .post(async(req, res) => { + const target = req.query.target; + const targetId = parseInt(req.query.targetId); + const { content } = req.body; + let data = {}; + if (target === 'article') { + data = { articleId: targetId, content } + } else if (target === 'product') { + data = { productId: targetId, content } + } else { + return res.status(400).json({ error: "Wrong target" }); + }; + try { + const comment = await prisma.comment.create({ + data + }); + res.status(201).json(comment); + } catch (error) { + res.status(500).json({ eror: "Failed to create comment" }); + } + }); + +commentRouter.route('/:id') + .patch(async(req, res) => { //id를 통해서 comment 수정하기 + const commentId = Number(req.params.id); + const { content } = req.body; + + try { + const updated = await prisma.comment.update({ + data: { + content, + }, + }); + res.status(201).json(updated); + } catch (err) { + res.status(500).json({ error: `Failed to modify comment` }); + } + }) + + .delete(async(req, res) => { //id를 통해서 comment 삭제하기 + const commentId = Number(req.params.id); + + try { + await prisma.comment.delete({ + where: { id: commentId }, + }); + res.json({ message: 'Comment deleted' }); + } catch (err) { + res.status(500).json({ error: `Can't deleted your comment` }); + } + }); + + commentRouter.route('/product') + .get(async(req, res) => { + const targetId = parseInt(req.query.targetId); + const lastId = req.query.lastId ? parseInt(req.query.lastId) : null; + try { + const comments = await prisma.comment.findMany({ + where: { + AND: [ + { + articleId: null + },{ + productId: targetId + }, + ], + }, + take: 5, + skip: lastId ? 1: 0, + ...(lastId && { cursor: { id: lastId } }), + select: { + id: true, + content: true, + createdAt: true, + }, + }); + res.status(201).json(comments); + } catch (err) { + console.error(err); + res.status(404).json({ error: `Can't find comments`}); + } + }); + + commentRouter.route('/article') + .get(async(req, res) => { + const targetId = parseInt(req.query.targetId); + const lastId = req.query.lastId ? parseInt(req.query.lastId) : null; + try { + const comments = await prisma.comment.findMany({ + where: { + AND: [ + { + articleId: targetId + },{ + productId: null + }, + ], + }, + take: 5, + skip: lastId ? 1: 0, + ...(lastId && { cursor: { id: lastId } }), + select: { + id: true, + content: true, + createdAt: true, + }, + }); + res.status(201).json(comments); + } catch (err) { + console.error(err); + res.status(404).json({ error: `Can't find comments`}); + } + }); + + //하나의 코드로 article과 product의 덧글을 조회하려고 했는데 targetId 대상 외 거르는 과정이 너무 어렵네요 ㅠ +// commentRouter.route('/') +// .get(async(req, res ) => { +// const target = req.query.target; +// const targetId = parseInt(req.query.targetId); +// let purpose = {}; +// if (target === 'articleId') { +// purpose = {articleId: targetId} +// } else if (target === 'productId') { +// purpose = {productId: targetId} +// } else { +// return res.status(400).json({ error: "Wrong target" }); +// }; +// try { +// const comments = await prisma.comment.findMany({ +// where: { +// ...purpose +// }, +// select: { +// id: true, +// content: true, +// createdAt: true, +// }, +// }); +// res.status(201).json(comments); +// } catch (err) { +// console.error(err); +// res.status(404).json({ error: `Can't find comments`}); +// } +// }); + +export default commentRouter; diff --git a/mission3/src/router/productRouter.js b/mission3/src/router/productRouter.js new file mode 100644 index 000000000..b91a7f05a --- /dev/null +++ b/mission3/src/router/productRouter.js @@ -0,0 +1,140 @@ +import { PrismaClient } from '@prisma/client'; +import express from 'express'; +import z from 'zod'; + +const productRouter = express.Router(); + +const prisma = new PrismaClient(); + +const createPorductSchema = z.object({ + name: z.string().min(1, { message: "이름을 입력해주세요" }), + description: z.string().min(10, { message: "설명은 최소 10자 이상이어야 합니다." }).max(100, { message: "설명은 최대 100자까지 가능합니다." }), + price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }), + tags: z.string().min(1, { message: "태그는 한개 이상이여야 합니다" }), +}); + +productRouter.route('/') + .post(async(req, res) => { //Product 등록하기 + try { + const validatedData = createPorductSchema.parse(req.body); + } catch (err) { + res.status(404).json({ error: msg.error }); + }; + const { name, description, price, tags } = validatedData; + + try { + const product = await prisma.product.create ({ + data: { + name, + description, + price, + tags + }, + }); + res.json({ message: 'Complete to post your product!' }); + } catch (error) { + console.error(error); + res.status(500).json({ error: 'Failed to post product' }); + } + }) + + .get(async(req, res) => { //검색어로 Product 조회하기 및 전체 Product 조회하기 + try { + const page = parseInt(req.query.page); + const keyword = req.query.keyword; + const where = keyword + ? { + OR: [ + { + name: { + contains: keyword, + }, + }, + { + description: { + contains: keyword, + }, + }, + ], + } + : undefined; + + const products = await prisma.product.findMany({ + skip: (page - 1) * 5, + take: 5, + orderBy: { + createdAt: 'asc', + }, + select: { + id: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + where + }); + res.status(201).json(products); + } catch (error) { + console.error(error); + res.status(404).json({ error: `Can't find products`}) + } + }); + +productRouter.route('/:id') + .patch(async(req, res) => { //id를 통해서 Product 수정하기 + const productId = Number(req.params.id); + const { name, description, price, tags } = req.body; + + try{ + const updated = await prisma.product.update({ + where: { id: productId }, + data: { + name, + description, + price, + tags, + }, + }); + res.status(201).json(updated); + } catch (err) { + res.status(500).json({ error: `Product is not modified` }); + } +}) + + .delete(async(req, res) => { //id를 통해서 Product 삭제하기 + const productId = Number(req.params.id); + + try { + await prisma.product.delete({ + where: { id: productId }, + }); + res.json({ message: 'Product is deleted' }); + } catch (err) { + res.status(404).json({ error: `Can't delete product` }); + } +}) + + .get(async(req, res) => { //id를 통해서 Product 조회하기 + const productId = Number(req.params.id); + + try { + const product = await prisma.product.findUnique({ + where: { id: productId }, + select: { + id: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + }); + res.status(201).json(product); + } catch (err) { + res.status(404).json({ error: `Can't find products`}) + } + }); + +export default productRouter; From 23e06e38702f1cd9ec9471b6238485e4a62fdf32 Mon Sep 17 00:00:00 2001 From: baturs Date: Fri, 8 Aug 2025 13:08:29 +0900 Subject: [PATCH 14/38] Upload modified post method --- mission3/src/router/articleRouter.js | 35 ++++++++++++++-------------- mission3/src/router/commentRouter.js | 1 + mission3/src/router/productRouter.js | 34 +++++++++++++-------------- 3 files changed, 34 insertions(+), 36 deletions(-) diff --git a/mission3/src/router/articleRouter.js b/mission3/src/router/articleRouter.js index e80a68771..a5b32d778 100644 --- a/mission3/src/router/articleRouter.js +++ b/mission3/src/router/articleRouter.js @@ -1,37 +1,36 @@ import { PrismaClient } from '@prisma/client'; import express from 'express'; -import z from 'zod'; +import { z } from 'zod'; const articleRouter = express.Router(); const prisma = new PrismaClient(); -const createArticleSchema = z.object({ +const Schema = z.object({ title: z.string().min(1, { message: "제목을 입력해주세요" }), - content: z.string().min(30, { message: "내용은 최소 30자 이상이어야 합니다." }).max(200, { message: "내용은 최대 200자까지 가능합니다." }), + content: z.string().min(10, { message: "내용은 최소 10자 이상이어야 합니다." }).max(200, { message: "내용은 최대 200자까지 가능합니다." }), }); articleRouter.route('/') //Article 등록하기 .post(async(req, res) => { try { - const validatedData = createArticleSchema.parse(req.body); - } catch (err) { - res.status(404).json({ error: msg.error }); - }; - const { title, content } = validatedData; + const validatedData = Schema.parse(req.body); + const article = await prisma.article.create({ + data: { + title: validatedData.title, + content: validatedData.content, + }, + }); - try { - const article = await prisma.article.create({ - data: { - title, - content, - }, - }); - res.json({ message: 'Complete to post your article!' }); + return res.status(201).json(article); } catch (err) { - res.status(500).json({ error: 'Article is not posted' }); + if (err instanceof z.ZodError) { + return res.status(400).json({ error: err.errors }); + } + + return res.status(500).json({ error: 'Article is not posted'}); } -}) + }) .get(async(req, res) => { //검색어로 Article 조회 및 전체 Article 조회 try { diff --git a/mission3/src/router/commentRouter.js b/mission3/src/router/commentRouter.js index 4b57e666e..654301217 100644 --- a/mission3/src/router/commentRouter.js +++ b/mission3/src/router/commentRouter.js @@ -36,6 +36,7 @@ commentRouter.route('/:id') try { const updated = await prisma.comment.update({ + where: { id: commentId }, data: { content, }, diff --git a/mission3/src/router/productRouter.js b/mission3/src/router/productRouter.js index b91a7f05a..758ecf655 100644 --- a/mission3/src/router/productRouter.js +++ b/mission3/src/router/productRouter.js @@ -6,7 +6,7 @@ const productRouter = express.Router(); const prisma = new PrismaClient(); -const createPorductSchema = z.object({ +const schema = z.object({ name: z.string().min(1, { message: "이름을 입력해주세요" }), description: z.string().min(10, { message: "설명은 최소 10자 이상이어야 합니다." }).max(100, { message: "설명은 최대 100자까지 가능합니다." }), price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }), @@ -16,27 +16,25 @@ const createPorductSchema = z.object({ productRouter.route('/') .post(async(req, res) => { //Product 등록하기 try { - const validatedData = createPorductSchema.parse(req.body); - } catch (err) { - res.status(404).json({ error: msg.error }); - }; - const { name, description, price, tags } = validatedData; - - try { + const validatedData = schema.parse(req.body); const product = await prisma.product.create ({ data: { - name, - description, - price, - tags - }, + name: validatedData.name, + description: validatedData.description, + price: validatedData.price, + tags: validatedData.tags, + }, }); - res.json({ message: 'Complete to post your product!' }); - } catch (error) { - console.error(error); - res.status(500).json({ error: 'Failed to post product' }); + + return res.status(201).json(product); + } catch (err) { + if (err instanceof z.ZodError) { + return res.status(400).json({ error: err. errors }); } - }) + + return res.status(500).json({ error: 'Product is not posted' }); + } +}) .get(async(req, res) => { //검색어로 Product 조회하기 및 전체 Product 조회하기 try { From 0d4ec3b7ea742756f6aafcc4518ea7523906e042 Mon Sep 17 00:00:00 2001 From: baturs Date: Fri, 8 Aug 2025 14:27:22 +0900 Subject: [PATCH 15/38] add annotations --- mission3/prisma/seed.js | 12 +++++++++ mission3/src/app.js | 14 ++++------ mission3/src/router/articleRouter.js | 39 ++++++++++++++-------------- mission3/src/router/commentRouter.js | 28 ++++++++++---------- mission3/src/router/productRouter.js | 27 +++++++++---------- 5 files changed, 66 insertions(+), 54 deletions(-) diff --git a/mission3/prisma/seed.js b/mission3/prisma/seed.js index fc0affadc..ca7198df3 100644 --- a/mission3/prisma/seed.js +++ b/mission3/prisma/seed.js @@ -17,6 +17,18 @@ const main = async () => { content: 'Article 테스트 글입니다.', }, }); + await prisma.comment.create({ + data: { + content: 'Article comment 테스트', + articleId: 1 + } + }); + await prisma.comment.create({ + data: { + content: 'Product comment 테스트', + productId: 1 + } + }); }; diff --git a/mission3/src/app.js b/mission3/src/app.js index 6ea45c5be..1d47a63d4 100644 --- a/mission3/src/app.js +++ b/mission3/src/app.js @@ -2,6 +2,7 @@ import express from 'express'; import multer from 'multer'; import cors from 'cors'; import { PrismaClient } from '@prisma/client'; +//./router에서 각 router들 불러내기 import productRouter from './router/productRouter.js'; import articleRouter from './router/articleRouter.js'; import commentRouter from './router/commentRouter.js'; @@ -20,27 +21,22 @@ app.use('/products', productRouter); app.use('/articles', articleRouter); app.use('/comments', commentRouter); -const upload = multer({ dest: 'uploads/'}) +const upload = multer({ dest: 'uploads/'}) // multer를 통해 업로드된 사진이 저장될 폴더 -app.post('/photos', upload.single('image'), (req, res) => { +app.post('/photos', upload.single('image'), (req, res) => { // ./photo라는 경로에서 ./uploads/에 있는 파일을 서빙 const path = 'download/' + req.file.filename; - res.json({ path }); + res.json({ path }); // 업로드 됬을 시, 사진의 저장된 위치를 알려줌으로써 확인 가능 }); app.use('/downlaod', express.static('uploads')); -const corsOptions = { +const corsOptions = { //CORS 설정 origin: 'http://localhost:3000', optionSuccessStatus: 200 } app.use(cors(corsOptions)); -// app.use((err, res, res, next) => { -// console.error(err.stack); -// res.status(500).send('Something broke!'); -// }); - const port = 3000; app.listen(port, () => { console.log(`Server is running on http://localhost:${port}`); diff --git a/mission3/src/router/articleRouter.js b/mission3/src/router/articleRouter.js index a5b32d778..d1970b28a 100644 --- a/mission3/src/router/articleRouter.js +++ b/mission3/src/router/articleRouter.js @@ -6,15 +6,15 @@ const articleRouter = express.Router(); const prisma = new PrismaClient(); -const Schema = z.object({ +const schema = z.object({ //유효성 검사 설정하기 title: z.string().min(1, { message: "제목을 입력해주세요" }), content: z.string().min(10, { message: "내용은 최소 10자 이상이어야 합니다." }).max(200, { message: "내용은 최대 200자까지 가능합니다." }), }); -articleRouter.route('/') //Article 등록하기 +articleRouter.route('/') // Zod로 유효성 검사에서 통과한 데이터를 article table에 post하기 .post(async(req, res) => { try { - const validatedData = Schema.parse(req.body); + const validatedData = schema.parse(req.body); const article = await prisma.article.create({ data: { title: validatedData.title, @@ -24,28 +24,29 @@ articleRouter.route('/') //Article 등록하기 return res.status(201).json(article); } catch (err) { - if (err instanceof z.ZodError) { - return res.status(400).json({ error: err.errors }); - } - - return res.status(500).json({ error: 'Article is not posted'}); + if (err instanceof z.ZodError) { //유효성 검사에 통과하지 못하면 400에러창이 출력 + console.error(err); + res.status(400).json({ error: err. errors }); } - }) + console.error(err); + res.status(500).json({ error: 'Article is not posted' }); //그외는 500에러로 출력 + } +}) - .get(async(req, res) => { //검색어로 Article 조회 및 전체 Article 조회 + .get(async(req, res) => { //page와 keyword query를 통해서 원하는 article 찾기 try { const page = parseInt(req.query.page); const keyword = req.query.keyword; - const where = keyword + const where = keyword //title과 content 에서 원하는 keyword가 있는 데이터를 찾도록 만든 변수 ? { OR: [ { - name: { + title: { contains: keyword, }, }, { - description: { + content: { contains: keyword, }, }, @@ -54,10 +55,10 @@ articleRouter.route('/') //Article 등록하기 : undefined; const articles = await prisma.article.findMany({ - skip: (page - 1) * 5, + skip: (page - 1) * 5, //offset pagination take: 5, - orderBy: { - createdAt: 'asc', + orderBy: { // 아스키 코드가 느린 순새대로 정렬하기(최신순) + createdAt: 'desc', }, select: { id: true, @@ -75,7 +76,7 @@ articleRouter.route('/') //Article 등록하기 }); articleRouter.route('/:id') - .patch(async(req, res) => { //id를 통해 Article 수정하기 + .patch(async(req, res) => { // Id를 통해서 article를 찾아내 수정하기 const articleId = Number(req.params.id); const { title, content } = req.body; @@ -93,7 +94,7 @@ articleRouter.route('/:id') } }) - .delete(async(req, res) => { //id통해서 Article 삭제하기 + .delete(async(req, res) => { // Id을 통해 article를 찾아내 삭제하기 const articleId = Number(req.params.id); try { @@ -106,7 +107,7 @@ articleRouter.route('/:id') } }) - .get(async(req, res) => { //id를 통해서 Article 조회하기 + .get(async(req, res) => { //id를 통해 article 조회하기 const articleId = Number(req.params.id); try { diff --git a/mission3/src/router/commentRouter.js b/mission3/src/router/commentRouter.js index 654301217..83d24c91b 100644 --- a/mission3/src/router/commentRouter.js +++ b/mission3/src/router/commentRouter.js @@ -1,17 +1,16 @@ import { PrismaClient } from '@prisma/client'; import express from 'express'; -import { string } from 'zod'; const commentRouter = express.Router(); const prisma = new PrismaClient(); commentRouter.route('/') - .post(async(req, res) => { + .post(async(req, res) => { //target query를 통해서 'articleId'와 'productId' 중 하나의 정보를 받고, targetId query를 통해서 세부 Id 정보를 받음 const target = req.query.target; const targetId = parseInt(req.query.targetId); const { content } = req.body; - let data = {}; + let data = {}; // target query에 알맞는 데이터 형식을 갖도록 만든 함수 if (target === 'article') { data = { articleId: targetId, content } } else if (target === 'product') { @@ -30,7 +29,7 @@ commentRouter.route('/') }); commentRouter.route('/:id') - .patch(async(req, res) => { //id를 통해서 comment 수정하기 + .patch(async(req, res) => { //Id 정보를 받고서 대조 후 알맞는 comment를 찾아 수정하기 const commentId = Number(req.params.id); const { content } = req.body; @@ -47,7 +46,7 @@ commentRouter.route('/:id') } }) - .delete(async(req, res) => { //id를 통해서 comment 삭제하기 + .delete(async(req, res) => { //id를 통해서 comment 찾기 후 삭제하기 const commentId = Number(req.params.id); try { @@ -61,12 +60,12 @@ commentRouter.route('/:id') }); commentRouter.route('/product') - .get(async(req, res) => { + .get(async(req, res) => { //targetId를 통해 지정된 product의 comment를 불러오기 const targetId = parseInt(req.query.targetId); - const lastId = req.query.lastId ? parseInt(req.query.lastId) : null; + const lastId = req.query.lastId ? parseInt(req.query.lastId) : null; //cursor 방식의 pagination을 하기 위한 lastId 상수 지정 try { const comments = await prisma.comment.findMany({ - where: { + where: { //article이 아니고 product의 comment를 골라내기 위해 만든 함수 AND: [ { articleId: null @@ -75,9 +74,9 @@ commentRouter.route('/:id') }, ], }, - take: 5, + take: 5, //첫 불러내는 comment가 총 5개 이고 lastId가 지정이 안되면 skip 의 값은 0이 되고 있다면 1로 설정 skip: lastId ? 1: 0, - ...(lastId && { cursor: { id: lastId } }), + ...(lastId && { cursor: { id: lastId } }), //lastId의 값이 주어졌을때 괄호가 풀어지며 내부의 'cursor: { id: lastId }가 작동함 select: { id: true, content: true, @@ -92,12 +91,12 @@ commentRouter.route('/:id') }); commentRouter.route('/article') - .get(async(req, res) => { + .get(async(req, res) => { //targetId를 통해 지정된 article의 comment를 불러오기 const targetId = parseInt(req.query.targetId); const lastId = req.query.lastId ? parseInt(req.query.lastId) : null; try { const comments = await prisma.comment.findMany({ - where: { + where: { //위와 반대로 product이 아니고 article의 comment를 골라내기 위해 만든 함수 AND: [ { articleId: targetId @@ -122,7 +121,10 @@ commentRouter.route('/:id') } }); - //하나의 코드로 article과 product의 덧글을 조회하려고 했는데 targetId 대상 외 거르는 과정이 너무 어렵네요 ㅠ +// 코드의 줄이 짧으면 짧으수록 좋다는 멘토님의 말씀이 떠올라서 1차적으로 target query 를 통해서 articleId, productId를 구별하도록 만들고 +// targetId query를 통해서 세부 Id를 비교해서 comment를 찾아내면서 targetId가 없을 경우 target의 유형의 comment를 전부 +// 불러오는 방법에서 막혔습니다.. + // commentRouter.route('/') // .get(async(req, res ) => { // const target = req.query.target; diff --git a/mission3/src/router/productRouter.js b/mission3/src/router/productRouter.js index 758ecf655..ab468a554 100644 --- a/mission3/src/router/productRouter.js +++ b/mission3/src/router/productRouter.js @@ -6,7 +6,7 @@ const productRouter = express.Router(); const prisma = new PrismaClient(); -const schema = z.object({ +const schema = z.object({ //유효성 검사 설정하기 name: z.string().min(1, { message: "이름을 입력해주세요" }), description: z.string().min(10, { message: "설명은 최소 10자 이상이어야 합니다." }).max(100, { message: "설명은 최대 100자까지 가능합니다." }), price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }), @@ -14,7 +14,7 @@ const schema = z.object({ }); productRouter.route('/') - .post(async(req, res) => { //Product 등록하기 + .post(async(req, res) => { // Zod로 유효성 검사에서 통과한 데이터를 product table에 post하기 try { const validatedData = schema.parse(req.body); const product = await prisma.product.create ({ @@ -28,19 +28,20 @@ productRouter.route('/') return res.status(201).json(product); } catch (err) { - if (err instanceof z.ZodError) { - return res.status(400).json({ error: err. errors }); + if (err instanceof z.ZodError) { //유효성 검사에 통과하지 못하면 400에러창이 출력 + console.error(err); + res.status(400).json({ error: err. errors }); } - - return res.status(500).json({ error: 'Product is not posted' }); + console.error(err); + res.status(500).json({ error: 'Product is not posted' }); //그외는 500에러로 출력 } }) - .get(async(req, res) => { //검색어로 Product 조회하기 및 전체 Product 조회하기 + .get(async(req, res) => { //page와 keyword query를 통해서 원하는 product 찾기 try { const page = parseInt(req.query.page); const keyword = req.query.keyword; - const where = keyword + const where = keyword //name과 description에서 원하는 keyword가 들어간 데이터를 찾도록 만든 변수 ? { OR: [ { @@ -60,8 +61,8 @@ productRouter.route('/') const products = await prisma.product.findMany({ skip: (page - 1) * 5, take: 5, - orderBy: { - createdAt: 'asc', + orderBy: { // 아스키 코드가 느린 순새대로 정렬하기(최신순) + createdAt: 'desc', }, select: { id: true, @@ -81,7 +82,7 @@ productRouter.route('/') }); productRouter.route('/:id') - .patch(async(req, res) => { //id를 통해서 Product 수정하기 + .patch(async(req, res) => { // Id를 통해서 product를 찾아내 수정하기 const productId = Number(req.params.id); const { name, description, price, tags } = req.body; @@ -101,7 +102,7 @@ productRouter.route('/:id') } }) - .delete(async(req, res) => { //id를 통해서 Product 삭제하기 + .delete(async(req, res) => { // Id을 통해 product를 찾아내 삭제하기 const productId = Number(req.params.id); try { @@ -114,7 +115,7 @@ productRouter.route('/:id') } }) - .get(async(req, res) => { //id를 통해서 Product 조회하기 + .get(async(req, res) => { //id를 통해 article 조회하기 const productId = Number(req.params.id); try { From 8c248f4054d0e952a97bd4f13109dca5ba9ce0e7 Mon Sep 17 00:00:00 2001 From: baturs Date: Fri, 8 Aug 2025 14:37:17 +0900 Subject: [PATCH 16/38] add seed about comment --- mission3/src/app.js | 2 +- mission3/src/router/articleRouter.js | 8 +++----- mission3/src/router/commentRouter.js | 2 +- mission3/src/router/productRouter.js | 8 +++----- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/mission3/src/app.js b/mission3/src/app.js index 1d47a63d4..5c3638415 100644 --- a/mission3/src/app.js +++ b/mission3/src/app.js @@ -30,7 +30,7 @@ app.post('/photos', upload.single('image'), (req, res) => { // ./photo라는 app.use('/downlaod', express.static('uploads')); -const corsOptions = { //CORS 설정 +const corsOptions = { //CORS 설정 및 whitelist로 'http://localhost:3000'을 설정 origin: 'http://localhost:3000', optionSuccessStatus: 200 } diff --git a/mission3/src/router/articleRouter.js b/mission3/src/router/articleRouter.js index d1970b28a..44e0f2797 100644 --- a/mission3/src/router/articleRouter.js +++ b/mission3/src/router/articleRouter.js @@ -25,11 +25,9 @@ articleRouter.route('/') // Zod로 유효성 검사에서 통과한 데이터를 return res.status(201).json(article); } catch (err) { if (err instanceof z.ZodError) { //유효성 검사에 통과하지 못하면 400에러창이 출력 - console.error(err); - res.status(400).json({ error: err. errors }); + return res.status(400).json({ error: err. errors }); } - console.error(err); - res.status(500).json({ error: 'Article is not posted' }); //그외는 500에러로 출력 + return res.status(500).json({ error: 'Article is not posted' }); //그외는 500에러로 출력 } }) @@ -57,7 +55,7 @@ articleRouter.route('/') // Zod로 유효성 검사에서 통과한 데이터를 const articles = await prisma.article.findMany({ skip: (page - 1) * 5, //offset pagination take: 5, - orderBy: { // 아스키 코드가 느린 순새대로 정렬하기(최신순) + orderBy: { // 최신 순서대로 정렬하기(최신순) createdAt: 'desc', }, select: { diff --git a/mission3/src/router/commentRouter.js b/mission3/src/router/commentRouter.js index 83d24c91b..dc9336c48 100644 --- a/mission3/src/router/commentRouter.js +++ b/mission3/src/router/commentRouter.js @@ -76,7 +76,7 @@ commentRouter.route('/:id') }, take: 5, //첫 불러내는 comment가 총 5개 이고 lastId가 지정이 안되면 skip 의 값은 0이 되고 있다면 1로 설정 skip: lastId ? 1: 0, - ...(lastId && { cursor: { id: lastId } }), //lastId의 값이 주어졌을때 괄호가 풀어지며 내부의 'cursor: { id: lastId }가 작동함 + ...(lastId && { cursor: { id: lastId } }), //lastId의 값이 있을때 괄호가 풀어지며 내부의 'cursor: { id: lastId }가 작동함 select: { id: true, content: true, diff --git a/mission3/src/router/productRouter.js b/mission3/src/router/productRouter.js index ab468a554..28b4cad78 100644 --- a/mission3/src/router/productRouter.js +++ b/mission3/src/router/productRouter.js @@ -29,11 +29,9 @@ productRouter.route('/') return res.status(201).json(product); } catch (err) { if (err instanceof z.ZodError) { //유효성 검사에 통과하지 못하면 400에러창이 출력 - console.error(err); - res.status(400).json({ error: err. errors }); + return res.status(400).json({ error: err. errors }); } - console.error(err); - res.status(500).json({ error: 'Product is not posted' }); //그외는 500에러로 출력 + return res.status(500).json({ error: 'Product is not posted' }); //그외는 500에러로 출력 } }) @@ -61,7 +59,7 @@ productRouter.route('/') const products = await prisma.product.findMany({ skip: (page - 1) * 5, take: 5, - orderBy: { // 아스키 코드가 느린 순새대로 정렬하기(최신순) + orderBy: { // 최신 순서대로 정렬하기(최신순) createdAt: 'desc', }, select: { From 9e2a66207094835dad0f04d60cd8505505313fb8 Mon Sep 17 00:00:00 2001 From: baturs Date: Mon, 11 Aug 2025 11:19:36 +0900 Subject: [PATCH 17/38] Modified err. parts --- mission3/src/router/articleRouter.js | 2 +- mission3/src/router/productRouter.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mission3/src/router/articleRouter.js b/mission3/src/router/articleRouter.js index 44e0f2797..5ff9940f2 100644 --- a/mission3/src/router/articleRouter.js +++ b/mission3/src/router/articleRouter.js @@ -25,7 +25,7 @@ articleRouter.route('/') // Zod로 유효성 검사에서 통과한 데이터를 return res.status(201).json(article); } catch (err) { if (err instanceof z.ZodError) { //유효성 검사에 통과하지 못하면 400에러창이 출력 - return res.status(400).json({ error: err. errors }); + return res.status(400).json({ error: err.errors }); } return res.status(500).json({ error: 'Article is not posted' }); //그외는 500에러로 출력 } diff --git a/mission3/src/router/productRouter.js b/mission3/src/router/productRouter.js index 28b4cad78..06ad28659 100644 --- a/mission3/src/router/productRouter.js +++ b/mission3/src/router/productRouter.js @@ -29,7 +29,7 @@ productRouter.route('/') return res.status(201).json(product); } catch (err) { if (err instanceof z.ZodError) { //유효성 검사에 통과하지 못하면 400에러창이 출력 - return res.status(400).json({ error: err. errors }); + return res.status(400).json({ error: err.errors }); } return res.status(500).json({ error: 'Product is not posted' }); //그외는 500에러로 출력 } From 299531c61b7a5ff31165338c8184c1971ea474f2 Mon Sep 17 00:00:00 2001 From: baturs Date: Mon, 11 Aug 2025 11:39:20 +0900 Subject: [PATCH 18/38] Modified error about data 0 --- mission3/src/router/articleRouter.js | 10 ++++++---- mission3/src/router/commentRouter.js | 4 ++-- mission3/src/router/productRouter.js | 10 ++++++---- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/mission3/src/router/articleRouter.js b/mission3/src/router/articleRouter.js index 5ff9940f2..05d63926a 100644 --- a/mission3/src/router/articleRouter.js +++ b/mission3/src/router/articleRouter.js @@ -33,24 +33,26 @@ articleRouter.route('/') // Zod로 유효성 검사에서 통과한 데이터를 .get(async(req, res) => { //page와 keyword query를 통해서 원하는 article 찾기 try { - const page = parseInt(req.query.page); - const keyword = req.query.keyword; + const page = parseInt(req.query.page) || 1; + const keyword = req.query.keyword || ''; const where = keyword //title과 content 에서 원하는 keyword가 있는 데이터를 찾도록 만든 변수 ? { OR: [ { title: { contains: keyword, + mode: 'insensitive', //대소문자 구분 없이 검색하기 위해 }, }, { content: { contains: keyword, + mode: 'insensitive', }, }, ], } - : undefined; + : {}; //기본값 {}으로 빈 객체를 수식하기 위함 const articles = await prisma.article.findMany({ skip: (page - 1) * 5, //offset pagination @@ -64,7 +66,7 @@ articleRouter.route('/') // Zod로 유효성 검사에서 통과한 데이터를 content: true, createdAt: true, }, - where + where, }); res.status(201).json(articles); } catch (error) { diff --git a/mission3/src/router/commentRouter.js b/mission3/src/router/commentRouter.js index dc9336c48..9d85c6259 100644 --- a/mission3/src/router/commentRouter.js +++ b/mission3/src/router/commentRouter.js @@ -61,7 +61,7 @@ commentRouter.route('/:id') commentRouter.route('/product') .get(async(req, res) => { //targetId를 통해 지정된 product의 comment를 불러오기 - const targetId = parseInt(req.query.targetId); + const targetId = parseInt(req.query.targetId) || 1; const lastId = req.query.lastId ? parseInt(req.query.lastId) : null; //cursor 방식의 pagination을 하기 위한 lastId 상수 지정 try { const comments = await prisma.comment.findMany({ @@ -92,7 +92,7 @@ commentRouter.route('/:id') commentRouter.route('/article') .get(async(req, res) => { //targetId를 통해 지정된 article의 comment를 불러오기 - const targetId = parseInt(req.query.targetId); + const targetId = parseInt(req.query.targetId) || 1; const lastId = req.query.lastId ? parseInt(req.query.lastId) : null; try { const comments = await prisma.comment.findMany({ diff --git a/mission3/src/router/productRouter.js b/mission3/src/router/productRouter.js index 06ad28659..51feea600 100644 --- a/mission3/src/router/productRouter.js +++ b/mission3/src/router/productRouter.js @@ -37,24 +37,26 @@ productRouter.route('/') .get(async(req, res) => { //page와 keyword query를 통해서 원하는 product 찾기 try { - const page = parseInt(req.query.page); - const keyword = req.query.keyword; + const page = parseInt(req.query.page) || 1; //값이 없을 경우도 수식하기 위함 + const keyword = req.query.keyword || ''; const where = keyword //name과 description에서 원하는 keyword가 들어간 데이터를 찾도록 만든 변수 ? { OR: [ { name: { contains: keyword, + mode: 'insensitive', //대소문자 구분 없이 검색하기 위해 }, }, { description: { contains: keyword, + mode: 'insensitive', }, }, ], } - : undefined; + : {}; //기본값 {}으로 빈 객체를 수식하기 위함 const products = await prisma.product.findMany({ skip: (page - 1) * 5, @@ -70,7 +72,7 @@ productRouter.route('/') tags: true, createdAt: true, }, - where + where, }); res.status(201).json(products); } catch (error) { From e501e2463f8b483d8548ce73767c5da09a07558b Mon Sep 17 00:00:00 2001 From: baturs Date: Mon, 11 Aug 2025 13:59:50 +0900 Subject: [PATCH 19/38] typo correction --- mission3/src/router/articleRouter.js | 28 ++++++++++++++-------------- mission3/src/router/commentRouter.js | 18 +++++++++--------- mission3/src/router/productRouter.js | 28 ++++++++++++++-------------- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/mission3/src/router/articleRouter.js b/mission3/src/router/articleRouter.js index 05d63926a..bab456be6 100644 --- a/mission3/src/router/articleRouter.js +++ b/mission3/src/router/articleRouter.js @@ -27,7 +27,7 @@ articleRouter.route('/') // Zod로 유효성 검사에서 통과한 데이터를 if (err instanceof z.ZodError) { //유효성 검사에 통과하지 못하면 400에러창이 출력 return res.status(400).json({ error: err.errors }); } - return res.status(500).json({ error: 'Article is not posted' }); //그외는 500에러로 출력 + return res.status(500).json({ error: 'Internal Server Error' }); //그외는 500에러로 출력 } }) @@ -68,29 +68,29 @@ articleRouter.route('/') // Zod로 유효성 검사에서 통과한 데이터를 }, where, }); - res.status(201).json(articles); + res.status(200).json(articles); } catch (error) { console.error(error); - res.status(404).json({ error: `Can't find articles`}) + res.status(404).json({ error: 'Failed to find article' }) } }); articleRouter.route('/:id') .patch(async(req, res) => { // Id를 통해서 article를 찾아내 수정하기 const articleId = Number(req.params.id); - const { title, content } = req.body; + const validatedData = schema.parse(req.body); try { const updated = await prisma.article.update({ where: { id: articleId }, data: { - title, - content, + title: validatedData.title, + content: validatedData.content, }, }); - res.status(201).json(updated); + res.status(200).json(updated); } catch (err) { - res.status(500).json({ error: err.message }); + res.status(404).json({ error: 'Failed to delete data' }); } }) @@ -99,11 +99,11 @@ articleRouter.route('/:id') try { await prisma.article.delete({ - wehre: { id: articleId }, + where: { id: articleId }, }); - res.json({ message: 'Article is deleted' }); + res.status(204); } catch (err) { - res.status(500).json({ error: err.message }); + res.status(500).json({ error: 'Internal Server Error' }); } }) @@ -111,7 +111,7 @@ articleRouter.route('/:id') const articleId = Number(req.params.id); try { - const article = await prisma.product.findUnique({ + const article = await prisma.article.findUnique({ where: { id: articleId }, select: { id: true, @@ -120,9 +120,9 @@ articleRouter.route('/:id') createdAt: true, }, }); - res.status(201).json(article); + res.status(200).json(article); } catch (err) { - res.status(404).json({ error: `Can't find article`}) + res.status(404).json({ error: 'Failed to find article' }) } }); diff --git a/mission3/src/router/commentRouter.js b/mission3/src/router/commentRouter.js index 9d85c6259..2ef66b644 100644 --- a/mission3/src/router/commentRouter.js +++ b/mission3/src/router/commentRouter.js @@ -24,7 +24,7 @@ commentRouter.route('/') }); res.status(201).json(comment); } catch (error) { - res.status(500).json({ eror: "Failed to create comment" }); + res.status(500).json({ error: 'Internal Server Error' }); } }); @@ -42,7 +42,7 @@ commentRouter.route('/:id') }); res.status(201).json(updated); } catch (err) { - res.status(500).json({ error: `Failed to modify comment` }); + res.status(404).json({ error: 'Failed to modify comment' }); } }) @@ -53,9 +53,9 @@ commentRouter.route('/:id') await prisma.comment.delete({ where: { id: commentId }, }); - res.json({ message: 'Comment deleted' }); + res.tatus(204).json({ message: 'Comment is deleted' }); } catch (err) { - res.status(500).json({ error: `Can't deleted your comment` }); + res.status(404).json({ error: 'Failed to delete data' }); } }); @@ -83,10 +83,10 @@ commentRouter.route('/:id') createdAt: true, }, }); - res.status(201).json(comments); + res.status(200).json(comments); } catch (err) { console.error(err); - res.status(404).json({ error: `Can't find comments`}); + res.status(404).json({ error: 'Failed to find comment' }) } }); @@ -117,7 +117,7 @@ commentRouter.route('/:id') res.status(201).json(comments); } catch (err) { console.error(err); - res.status(404).json({ error: `Can't find comments`}); + res.status(404).json({ error: 'Failed to find comment' }) } }); @@ -128,7 +128,7 @@ commentRouter.route('/:id') // commentRouter.route('/') // .get(async(req, res ) => { // const target = req.query.target; -// const targetId = parseInt(req.query.targetId); +// const targetId = parseInt(req.query.targetId) || 1; // let purpose = {}; // if (target === 'articleId') { // purpose = {articleId: targetId} @@ -151,7 +151,7 @@ commentRouter.route('/:id') // res.status(201).json(comments); // } catch (err) { // console.error(err); -// res.status(404).json({ error: `Can't find comments`}); +// res.status(404).json({ error: 'Failed to find comment' }) // } // }); diff --git a/mission3/src/router/productRouter.js b/mission3/src/router/productRouter.js index 51feea600..bcb04624b 100644 --- a/mission3/src/router/productRouter.js +++ b/mission3/src/router/productRouter.js @@ -31,7 +31,7 @@ productRouter.route('/') if (err instanceof z.ZodError) { //유효성 검사에 통과하지 못하면 400에러창이 출력 return res.status(400).json({ error: err.errors }); } - return res.status(500).json({ error: 'Product is not posted' }); //그외는 500에러로 출력 + return res.status(500).json({ error: 'Internal Server Error' }); //그외는 500에러로 출력 } }) @@ -74,31 +74,31 @@ productRouter.route('/') }, where, }); - res.status(201).json(products); + res.status(200).json(products); } catch (error) { console.error(error); - res.status(404).json({ error: `Can't find products`}) + res.status(404).json({ error: 'Failed to find product' }) } }); productRouter.route('/:id') .patch(async(req, res) => { // Id를 통해서 product를 찾아내 수정하기 const productId = Number(req.params.id); - const { name, description, price, tags } = req.body; + const validatedData = schema.parse(req.body); try{ const updated = await prisma.product.update({ where: { id: productId }, data: { - name, - description, - price, - tags, + name: validatedData.name, + description: validatedData.description, + price: validatedData.price, + tags: validatedData.tags, }, }); res.status(201).json(updated); } catch (err) { - res.status(500).json({ error: `Product is not modified` }); + res.status(404).json({ error: 'Failed to modify product data' }); } }) @@ -109,13 +109,13 @@ productRouter.route('/:id') await prisma.product.delete({ where: { id: productId }, }); - res.json({ message: 'Product is deleted' }); + res.status(204); } catch (err) { - res.status(404).json({ error: `Can't delete product` }); + res.status(404).json({ error: 'Failed to delete data' }); } }) - .get(async(req, res) => { //id를 통해 article 조회하기 + .get(async(req, res) => { //id를 통해 product 조회하기 const productId = Number(req.params.id); try { @@ -130,9 +130,9 @@ productRouter.route('/:id') createdAt: true, }, }); - res.status(201).json(product); + res.status(200).json(product); } catch (err) { - res.status(404).json({ error: `Can't find products`}) + res.status(404).json({ error: 'Failed to find product' }) } }); From 5ce69071f9d3f44d780c5e35b62fdccbca70c17b Mon Sep 17 00:00:00 2001 From: Batur-s Date: Thu, 14 Aug 2025 13:15:52 +0900 Subject: [PATCH 20/38] add error handler --- mission3/src/router/articleRouter.js | 53 ++++++++++++++-------- mission3/src/router/commentRouter.js | 66 +++++++++------------------- mission3/src/router/productRouter.js | 44 ++++++++++++------- 3 files changed, 84 insertions(+), 79 deletions(-) diff --git a/mission3/src/router/articleRouter.js b/mission3/src/router/articleRouter.js index bab456be6..e40c131b7 100644 --- a/mission3/src/router/articleRouter.js +++ b/mission3/src/router/articleRouter.js @@ -12,26 +12,23 @@ const schema = z.object({ //유효성 검사 설정하기 }); articleRouter.route('/') // Zod로 유효성 검사에서 통과한 데이터를 article table에 post하기 - .post(async(req, res) => { + .post(async(req, res, next) => { try { const validatedData = schema.parse(req.body); const article = await prisma.article.create({ - data: { - title: validatedData.title, - content: validatedData.content, - }, + data: { + title: validatedData.title, + content: validatedData.content, + }, }); return res.status(201).json(article); } catch (err) { - if (err instanceof z.ZodError) { //유효성 검사에 통과하지 못하면 400에러창이 출력 - return res.status(400).json({ error: err.errors }); + next(err); } - return res.status(500).json({ error: 'Internal Server Error' }); //그외는 500에러로 출력 - } }) - .get(async(req, res) => { //page와 keyword query를 통해서 원하는 article 찾기 + .get(async(req, res, next) => { //page와 keyword query를 통해서 원하는 article 찾기 try { const page = parseInt(req.query.page) || 1; const keyword = req.query.keyword || ''; @@ -68,15 +65,15 @@ articleRouter.route('/') // Zod로 유효성 검사에서 통과한 데이터를 }, where, }); + res.status(200).json(articles); } catch (error) { - console.error(error); - res.status(404).json({ error: 'Failed to find article' }) + next(err); } }); articleRouter.route('/:id') - .patch(async(req, res) => { // Id를 통해서 article를 찾아내 수정하기 + .patch(async(req, res, next) => { // Id를 통해서 article를 찾아내 수정하기 const articleId = Number(req.params.id); const validatedData = schema.parse(req.body); @@ -90,24 +87,24 @@ articleRouter.route('/:id') }); res.status(200).json(updated); } catch (err) { - res.status(404).json({ error: 'Failed to delete data' }); + next(err); } }) - .delete(async(req, res) => { // Id을 통해 article를 찾아내 삭제하기 + .delete(async(req, res, next) => { // Id을 통해 article를 찾아내 삭제하기 const articleId = Number(req.params.id); try { await prisma.article.delete({ where: { id: articleId }, }); - res.status(204); + res.status(204).end(); } catch (err) { - res.status(500).json({ error: 'Internal Server Error' }); + next(err); } }) - .get(async(req, res) => { //id를 통해 article 조회하기 + .get(async(req, res, next) => { //id를 통해 article 조회하기 const articleId = Number(req.params.id); try { @@ -120,10 +117,28 @@ articleRouter.route('/:id') createdAt: true, }, }); + if (!article) { + return res.status(404).json({ error: 'Article not found'}); + } res.status(200).json(article); } catch (err) { - res.status(404).json({ error: 'Failed to find article' }) + next(err); } }); + + articleRouter.use((err, req, res, next) => { //에러 미드웨어 설정 + if (err instanceof z.ZodError) { + return res.status(400).json({ error: err.errors }); + } + + if (err.code === 'P2025') { + return res.status(404).json({ error: 'Record not found' }); + } + + console.error('unhandled Error:', err); + return res.status(500).json({ error: 'Internal Server Error' }); + }); + + export default articleRouter; diff --git a/mission3/src/router/commentRouter.js b/mission3/src/router/commentRouter.js index 2ef66b644..8433183db 100644 --- a/mission3/src/router/commentRouter.js +++ b/mission3/src/router/commentRouter.js @@ -6,7 +6,7 @@ const commentRouter = express.Router(); const prisma = new PrismaClient(); commentRouter.route('/') - .post(async(req, res) => { //target query를 통해서 'articleId'와 'productId' 중 하나의 정보를 받고, targetId query를 통해서 세부 Id 정보를 받음 + .post(async(req, res, next) => { //target query를 통해서 'articleId'와 'productId' 중 하나의 정보를 받고, targetId query를 통해서 세부 Id 정보를 받음 const target = req.query.target; const targetId = parseInt(req.query.targetId); const { content } = req.body; @@ -22,14 +22,15 @@ commentRouter.route('/') const comment = await prisma.comment.create({ data }); + res.status(201).json(comment); } catch (error) { - res.status(500).json({ error: 'Internal Server Error' }); + next(err); } }); commentRouter.route('/:id') - .patch(async(req, res) => { //Id 정보를 받고서 대조 후 알맞는 comment를 찾아 수정하기 + .patch(async(req, res, next) => { //Id 정보를 받고서 대조 후 알맞는 comment를 찾아 수정하기 const commentId = Number(req.params.id); const { content } = req.body; @@ -42,25 +43,26 @@ commentRouter.route('/:id') }); res.status(201).json(updated); } catch (err) { - res.status(404).json({ error: 'Failed to modify comment' }); + next(err); } }) - .delete(async(req, res) => { //id를 통해서 comment 찾기 후 삭제하기 + .delete(async(req, res, next) => { //id를 통해서 comment 찾기 후 삭제하기 const commentId = Number(req.params.id); try { await prisma.comment.delete({ where: { id: commentId }, }); - res.tatus(204).json({ message: 'Comment is deleted' }); + + res.status(204).end(); } catch (err) { - res.status(404).json({ error: 'Failed to delete data' }); + next(err); } }); commentRouter.route('/product') - .get(async(req, res) => { //targetId를 통해 지정된 product의 comment를 불러오기 + .get(async(req, res, next) => { //targetId를 통해 지정된 product의 comment를 불러오기 const targetId = parseInt(req.query.targetId) || 1; const lastId = req.query.lastId ? parseInt(req.query.lastId) : null; //cursor 방식의 pagination을 하기 위한 lastId 상수 지정 try { @@ -83,15 +85,15 @@ commentRouter.route('/:id') createdAt: true, }, }); + res.status(200).json(comments); } catch (err) { - console.error(err); - res.status(404).json({ error: 'Failed to find comment' }) + next(err); } }); commentRouter.route('/article') - .get(async(req, res) => { //targetId를 통해 지정된 article의 comment를 불러오기 + .get(async(req, res, next) => { //targetId를 통해 지정된 article의 comment를 불러오기 const targetId = parseInt(req.query.targetId) || 1; const lastId = req.query.lastId ? parseInt(req.query.lastId) : null; try { @@ -116,43 +118,17 @@ commentRouter.route('/:id') }); res.status(201).json(comments); } catch (err) { - console.error(err); - res.status(404).json({ error: 'Failed to find comment' }) + next(err); } }); -// 코드의 줄이 짧으면 짧으수록 좋다는 멘토님의 말씀이 떠올라서 1차적으로 target query 를 통해서 articleId, productId를 구별하도록 만들고 -// targetId query를 통해서 세부 Id를 비교해서 comment를 찾아내면서 targetId가 없을 경우 target의 유형의 comment를 전부 -// 불러오는 방법에서 막혔습니다.. + commentRouter.use((err, req, res, next) => { //에러 미드웨어 설정 + if (err.code === 'P2025') { + return res.status(404).json({ error: 'Record not found' }); + } -// commentRouter.route('/') -// .get(async(req, res ) => { -// const target = req.query.target; -// const targetId = parseInt(req.query.targetId) || 1; -// let purpose = {}; -// if (target === 'articleId') { -// purpose = {articleId: targetId} -// } else if (target === 'productId') { -// purpose = {productId: targetId} -// } else { -// return res.status(400).json({ error: "Wrong target" }); -// }; -// try { -// const comments = await prisma.comment.findMany({ -// where: { -// ...purpose -// }, -// select: { -// id: true, -// content: true, -// createdAt: true, -// }, -// }); -// res.status(201).json(comments); -// } catch (err) { -// console.error(err); -// res.status(404).json({ error: 'Failed to find comment' }) -// } -// }); + console.error('unhandled Error:', err); + return res.status(500).json({ error: 'Internal Server Error' }); + }); export default commentRouter; diff --git a/mission3/src/router/productRouter.js b/mission3/src/router/productRouter.js index bcb04624b..2a6ff2bc9 100644 --- a/mission3/src/router/productRouter.js +++ b/mission3/src/router/productRouter.js @@ -1,6 +1,6 @@ import { PrismaClient } from '@prisma/client'; import express from 'express'; -import z from 'zod'; +import { z } from 'zod'; const productRouter = express.Router(); @@ -14,7 +14,7 @@ const schema = z.object({ //유효성 검사 설정하기 }); productRouter.route('/') - .post(async(req, res) => { // Zod로 유효성 검사에서 통과한 데이터를 product table에 post하기 + .post(async(req, res, next) => { // Zod로 유효성 검사에서 통과한 데이터를 product table에 post하기 try { const validatedData = schema.parse(req.body); const product = await prisma.product.create ({ @@ -28,14 +28,11 @@ productRouter.route('/') return res.status(201).json(product); } catch (err) { - if (err instanceof z.ZodError) { //유효성 검사에 통과하지 못하면 400에러창이 출력 - return res.status(400).json({ error: err.errors }); + next(err); } - return res.status(500).json({ error: 'Internal Server Error' }); //그외는 500에러로 출력 - } }) - .get(async(req, res) => { //page와 keyword query를 통해서 원하는 product 찾기 + .get(async(req, res, next) => { //page와 keyword query를 통해서 원하는 product 찾기 try { const page = parseInt(req.query.page) || 1; //값이 없을 경우도 수식하기 위함 const keyword = req.query.keyword || ''; @@ -74,15 +71,15 @@ productRouter.route('/') }, where, }); + res.status(200).json(products); } catch (error) { - console.error(error); - res.status(404).json({ error: 'Failed to find product' }) + next(err); } }); productRouter.route('/:id') - .patch(async(req, res) => { // Id를 통해서 product를 찾아내 수정하기 + .patch(async(req, res, next) => { // Id를 통해서 product를 찾아내 수정하기 const productId = Number(req.params.id); const validatedData = schema.parse(req.body); @@ -98,20 +95,20 @@ productRouter.route('/:id') }); res.status(201).json(updated); } catch (err) { - res.status(404).json({ error: 'Failed to modify product data' }); + next(err); } }) - .delete(async(req, res) => { // Id을 통해 product를 찾아내 삭제하기 + .delete(async(req, res, next) => { // Id을 통해 product를 찾아내 삭제하기 const productId = Number(req.params.id); try { await prisma.product.delete({ where: { id: productId }, }); - res.status(204); + res.status(204).end(); } catch (err) { - res.status(404).json({ error: 'Failed to delete data' }); + next(err); } }) @@ -130,10 +127,27 @@ productRouter.route('/:id') createdAt: true, }, }); + if (!product) { + return res.status(404).json({ error: 'Product not found'}); + } res.status(200).json(product); } catch (err) { - res.status(404).json({ error: 'Failed to find product' }) + next(err); } }); + productRouter.use((err, req, res, next) => { //에러 미드웨어 설정 + if (err instanceof z.ZodError) { + return res.status(400).json({ error: err.errors }); + } + + if (err.code === 'P2025') { + return res.status(404).json({ error: 'Record not found' }); + } + + console.error('unhandled Error:', err); + return res.status(500).json({ error: 'Internal Server Error' }); + }); + + export default productRouter; From 2467edd055bdf03b6bc37cf4a50b209f666d4d3d Mon Sep 17 00:00:00 2001 From: Batur-s Date: Thu, 4 Sep 2025 17:48:09 +0900 Subject: [PATCH 21/38] Feat: add mission4 --- mission3/.gitignore | 1 + mission3/package-lock.json | 442 ++--- mission3/package.json | 4 +- mission4/.gitignore | 5 + mission4/package-lock.json | 1694 +++++++++++++++++ mission4/package.json | 32 + .../20250904083711_test/migration.sql | 94 + .../prisma/migrations/migration_lock.toml | 3 + mission4/prisma/schema.prisma | 75 + mission4/src/app.js | 36 + mission4/src/lib/constants.js | 21 + mission4/src/lib/passport/index.js | 10 + mission4/src/lib/passport/jwtStrategy.js | 39 + mission4/src/lib/passport/localStrategy.js | 27 + mission4/src/lib/prisma.js | 5 + mission4/src/lib/token.js | 27 + mission4/src/routers/articleRouter.js | 178 ++ mission4/src/routers/commentRouter.js | 187 ++ mission4/src/routers/index.js | 16 + mission4/src/routers/likeRouter.js | 188 ++ mission4/src/routers/productRouter.js | 188 ++ mission4/src/routers/userRouter.js | 209 ++ 22 files changed, 3209 insertions(+), 272 deletions(-) create mode 100644 mission4/.gitignore create mode 100644 mission4/package-lock.json create mode 100644 mission4/package.json create mode 100644 mission4/prisma/migrations/20250904083711_test/migration.sql create mode 100644 mission4/prisma/migrations/migration_lock.toml create mode 100644 mission4/prisma/schema.prisma create mode 100644 mission4/src/app.js create mode 100644 mission4/src/lib/constants.js create mode 100644 mission4/src/lib/passport/index.js create mode 100644 mission4/src/lib/passport/jwtStrategy.js create mode 100644 mission4/src/lib/passport/localStrategy.js create mode 100644 mission4/src/lib/prisma.js create mode 100644 mission4/src/lib/token.js create mode 100644 mission4/src/routers/articleRouter.js create mode 100644 mission4/src/routers/commentRouter.js create mode 100644 mission4/src/routers/index.js create mode 100644 mission4/src/routers/likeRouter.js create mode 100644 mission4/src/routers/productRouter.js create mode 100644 mission4/src/routers/userRouter.js diff --git a/mission3/.gitignore b/mission3/.gitignore index fdae56f2e..9f62ec0b8 100644 --- a/mission3/.gitignore +++ b/mission3/.gitignore @@ -1,4 +1,5 @@ node_modules # Keep environment variables out of version control +.env /generated/prisma diff --git a/mission3/package-lock.json b/mission3/package-lock.json index 5ffb28de2..c7e7aca46 100644 --- a/mission3/package-lock.json +++ b/mission3/package-lock.json @@ -16,32 +16,7 @@ "zod": "^4.0.14" }, "devDependencies": { - "prisma": "^6.13.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" + "prisma": "^6.15.0" } }, "node_modules/@prisma/client": { @@ -67,66 +42,66 @@ } }, "node_modules/@prisma/config": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.13.0.tgz", - "integrity": "sha512-OYMM+pcrvj/NqNWCGESSxVG3O7kX6oWuGyvufTUNnDw740KIQvNyA4v0eILgkpuwsKIDU36beZCkUtIt0naTog==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.15.0.tgz", + "integrity": "sha512-KMEoec9b2u6zX0EbSEx/dRpx1oNLjqJEBZYyK0S3TTIbZ7GEGoVyGyFRk4C72+A38cuPLbfQGQvgOD+gBErKlA==", "devOptional": true, "license": "Apache-2.0", "dependencies": { "c12": "3.1.0", "deepmerge-ts": "7.1.5", "effect": "3.16.12", - "read-package-up": "11.0.0" + "empathic": "2.0.0" } }, "node_modules/@prisma/debug": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.13.0.tgz", - "integrity": "sha512-um+9pfKJW0ihmM83id9FXGi5qEbVJ0Vxi1Gm0xpYsjwUBnw6s2LdPBbrsG9QXRX46K4CLWCTNvskXBup4i9hlw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.15.0.tgz", + "integrity": "sha512-y7cSeLuQmyt+A3hstAs6tsuAiVXSnw9T55ra77z0nbNkA8Lcq9rNcQg6PI00by/+WnE/aMRJ/W7sZWn2cgIy1g==", "devOptional": true, "license": "Apache-2.0" }, "node_modules/@prisma/engines": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.13.0.tgz", - "integrity": "sha512-D+1B79LFvtWA0KTt8ALekQ6A/glB9w10ETknH5Y9g1k2NYYQOQy93ffiuqLn3Pl6IPJG3EsK/YMROKEaq8KBrA==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.15.0.tgz", + "integrity": "sha512-opITiR5ddFJ1N2iqa7mkRlohCZqVSsHhRcc29QXeldMljOf4FSellLT0J5goVb64EzRTKcIDeIsJBgmilNcKxA==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "6.13.0", - "@prisma/engines-version": "6.13.0-35.361e86d0ea4987e9f53a565309b3eed797a6bcbd", - "@prisma/fetch-engine": "6.13.0", - "@prisma/get-platform": "6.13.0" + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/fetch-engine": "6.15.0", + "@prisma/get-platform": "6.15.0" } }, "node_modules/@prisma/engines-version": { - "version": "6.13.0-35.361e86d0ea4987e9f53a565309b3eed797a6bcbd", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.13.0-35.361e86d0ea4987e9f53a565309b3eed797a6bcbd.tgz", - "integrity": "sha512-MpPyKSzBX7P/ZY9odp9TSegnS/yH3CSbchQE9f0yBg3l2QyN59I6vGXcoYcqKC9VTniS1s18AMmhyr1OWavjHg==", + "version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb.tgz", + "integrity": "sha512-a/46aK5j6L3ePwilZYEgYDPrhBQ/n4gYjLxT5YncUTJJNRnTCVjPF86QdzUOLRdYjCLfhtZp9aum90W0J+trrg==", "devOptional": true, "license": "Apache-2.0" }, "node_modules/@prisma/fetch-engine": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.13.0.tgz", - "integrity": "sha512-grmmq+4FeFKmaaytA8Ozc2+Tf3BC8xn/DVJos6LL022mfRlMZYjT3hZM0/xG7+5fO95zFG9CkDUs0m1S2rXs5Q==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.15.0.tgz", + "integrity": "sha512-xcT5f6b+OWBq6vTUnRCc7qL+Im570CtwvgSj+0MTSGA1o9UDSKZ/WANvwtiRXdbYWECpyC3CukoG3A04VTAPHw==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "6.13.0", - "@prisma/engines-version": "6.13.0-35.361e86d0ea4987e9f53a565309b3eed797a6bcbd", - "@prisma/get-platform": "6.13.0" + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/get-platform": "6.15.0" } }, "node_modules/@prisma/get-platform": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.13.0.tgz", - "integrity": "sha512-Nii2pX50fY4QKKxQwm7/vvqT6Ku8yYJLZAFX4e2vzHwRdMqjugcOG5hOSLjxqoXb0cvOspV70TOhMzrw8kqAnw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.15.0.tgz", + "integrity": "sha512-Jbb+Xbxyp05NSR1x2epabetHiXvpO8tdN2YNoWoA/ZsbYyxxu/CO/ROBauIFuMXs3Ti+W7N7SJtWsHGaWte9Rg==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "6.13.0" + "@prisma/debug": "6.15.0" } }, "node_modules/@standard-schema/spec": { @@ -136,13 +111,6 @@ "devOptional": true, "license": "MIT" }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "devOptional": true, - "license": "MIT" - }, "node_modules/accepts": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", @@ -427,10 +395,9 @@ "license": "MIT" }, "node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "devOptional": true, + "version": "17.2.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", + "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -613,19 +580,6 @@ "node": ">= 0.8" } }, - "node_modules/find-up-simple": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", - "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -744,19 +698,6 @@ "node": ">= 0.4" } }, - "node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", - "devOptional": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -794,19 +735,6 @@ "node": ">=0.10.0" } }, - "node_modules/index-to-position": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.1.0.tgz", - "integrity": "sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -838,19 +766,90 @@ "jiti": "lib/jiti-cli.mjs" } }, - "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==", - "devOptional": true, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", + "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.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "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==", "license": "MIT" }, - "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "devOptional": true, - "license": "ISC" + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" }, "node_modules/math-intrinsics": { "version": "1.1.0", @@ -1001,25 +1000,21 @@ } }, "node_modules/node-fetch-native": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.6.tgz", - "integrity": "sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", "devOptional": true, "license": "MIT" }, - "node_modules/normalize-package-data": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", - "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", - "devOptional": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^7.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" } }, "node_modules/nypm": { @@ -1091,31 +1086,48 @@ "wrappy": "1" } }, - "node_modules/parse-json": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", - "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", - "devOptional": true, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "index-to-position": "^1.1.0", - "type-fest": "^4.39.1" + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" }, "engines": { - "node": ">=18" + "node": ">= 0.4.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "node_modules/passport-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">= 0.4.0" + } + }, + "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-to-regexp": { @@ -1141,17 +1153,10 @@ "devOptional": true, "license": "MIT" }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "devOptional": true, - "license": "ISC" - }, "node_modules/pkg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.2.0.tgz", - "integrity": "sha512-2SM/GZGAEkPp3KWORxQZns4M+WSeXbC2HEvmOIJe3Cmiv6ieAJvdVhDldtHqM5J1Y7MrR1XhkBT/rMlhh9FdqQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", "devOptional": true, "license": "MIT", "dependencies": { @@ -1161,15 +1166,15 @@ } }, "node_modules/prisma": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.13.0.tgz", - "integrity": "sha512-dfzORf0AbcEyyzxuv2lEwG8g+WRGF/qDQTpHf/6JoHsyF5MyzCEZwClVaEmw3WXcobgadosOboKUgQU0kFs9kw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.15.0.tgz", + "integrity": "sha512-E6RCgOt+kUVtjtZgLQDBJ6md2tDItLJNExwI0XJeBc1FKL+Vwb+ovxXxuok9r8oBgsOXBA33fGDuE/0qDdCWqQ==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/config": "6.13.0", - "@prisma/engines": "6.13.0" + "@prisma/config": "6.15.0", + "@prisma/engines": "6.15.0" }, "bin": { "prisma": "build/index.js" @@ -1266,44 +1271,6 @@ "destr": "^2.0.3" } }, - "node_modules/read-package-up": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz", - "integrity": "sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "find-up-simple": "^1.0.0", - "read-pkg": "^9.0.0", - "type-fest": "^4.6.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", - "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@types/normalize-package-data": "^2.4.3", - "normalize-package-data": "^6.0.0", - "parse-json": "^8.0.0", - "type-fest": "^4.6.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -1378,7 +1345,6 @@ "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "devOptional": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -1502,42 +1468,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "devOptional": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.21", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", - "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", - "devOptional": true, - "license": "CC0-1.0" - }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -1580,19 +1510,6 @@ "node": ">=0.6" } }, - "node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "devOptional": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/type-is": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", @@ -1613,19 +1530,6 @@ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", "license": "MIT" }, - "node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -1641,15 +1545,13 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" } }, "node_modules/vary": { diff --git a/mission3/package.json b/mission3/package.json index adacf9860..a02a1c4f5 100644 --- a/mission3/package.json +++ b/mission3/package.json @@ -17,9 +17,9 @@ "zod": "^4.0.14" }, "devDependencies": { - "prisma": "^6.13.0" + "prisma": "^6.15.0" }, - "prisma": { + "prisma": { "seed": "node prisma/seed.js" } } diff --git a/mission4/.gitignore b/mission4/.gitignore new file mode 100644 index 000000000..9f62ec0b8 --- /dev/null +++ b/mission4/.gitignore @@ -0,0 +1,5 @@ +node_modules +# Keep environment variables out of version control +.env + +/generated/prisma diff --git a/mission4/package-lock.json b/mission4/package-lock.json new file mode 100644 index 000000000..55d43f241 --- /dev/null +++ b/mission4/package-lock.json @@ -0,0 +1,1694 @@ +{ + "name": "mission3", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mission3", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@prisma/client": "^6.13.0", + "bcrypt": "^6.0.0", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^17.2.2", + "express": "^5.1.0", + "multer": "^2.0.2", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", + "passport-local": "^1.0.0", + "zod": "^4.0.14" + }, + "devDependencies": { + "prisma": "^6.15.0" + } + }, + "node_modules/@prisma/client": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.13.0.tgz", + "integrity": "sha512-8m2+I3dQovkV8CkDMluiwEV1TxV9EXdT6xaCz39O6jYw7mkf5gwfmi+cL4LJsEPwz5tG7sreBwkRpEMJedGYUQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "prisma": "*", + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@prisma/config": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.15.0.tgz", + "integrity": "sha512-KMEoec9b2u6zX0EbSEx/dRpx1oNLjqJEBZYyK0S3TTIbZ7GEGoVyGyFRk4C72+A38cuPLbfQGQvgOD+gBErKlA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "c12": "3.1.0", + "deepmerge-ts": "7.1.5", + "effect": "3.16.12", + "empathic": "2.0.0" + } + }, + "node_modules/@prisma/debug": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.15.0.tgz", + "integrity": "sha512-y7cSeLuQmyt+A3hstAs6tsuAiVXSnw9T55ra77z0nbNkA8Lcq9rNcQg6PI00by/+WnE/aMRJ/W7sZWn2cgIy1g==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.15.0.tgz", + "integrity": "sha512-opITiR5ddFJ1N2iqa7mkRlohCZqVSsHhRcc29QXeldMljOf4FSellLT0J5goVb64EzRTKcIDeIsJBgmilNcKxA==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/fetch-engine": "6.15.0", + "@prisma/get-platform": "6.15.0" + } + }, + "node_modules/@prisma/engines-version": { + "version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb.tgz", + "integrity": "sha512-a/46aK5j6L3ePwilZYEgYDPrhBQ/n4gYjLxT5YncUTJJNRnTCVjPF86QdzUOLRdYjCLfhtZp9aum90W0J+trrg==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.15.0.tgz", + "integrity": "sha512-xcT5f6b+OWBq6vTUnRCc7qL+Im570CtwvgSj+0MTSGA1o9UDSKZ/WANvwtiRXdbYWECpyC3CukoG3A04VTAPHw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/get-platform": "6.15.0" + } + }, + "node_modules/@prisma/get-platform": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.15.0.tgz", + "integrity": "sha512-Jbb+Xbxyp05NSR1x2epabetHiXvpO8tdN2YNoWoA/ZsbYyxxu/CO/ROBauIFuMXs3Ti+W7N7SJtWsHGaWte9Rg==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "license": "MIT" + }, + "node_modules/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.0", + "node-gyp-build": "^4.8.4" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "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==", + "license": "BSD-3-Clause" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/c12": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", + "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.3", + "confbox": "^0.2.2", + "defu": "^6.1.4", + "dotenv": "^16.6.1", + "exsolve": "^1.0.7", + "giget": "^2.0.0", + "jiti": "^2.4.2", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^1.0.0", + "pkg-types": "^2.2.0", + "rc9": "^2.1.2" + }, + "peerDependencies": { + "magicast": "^0.3.5" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } + } + }, + "node_modules/c12/node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "devOptional": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "consola": "^3.2.3" + } + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deepmerge-ts": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", + "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/dotenv": { + "version": "17.2.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", + "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "license": "Apache-2.0", + "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", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/effect": { + "version": "3.16.12", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.16.12.tgz", + "integrity": "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "fast-check": "^3.23.1" + } + }, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/fast-check": { + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", + "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "dependencies": { + "pure-rand": "^6.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/giget": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", + "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.0", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.6", + "nypm": "^0.6.0", + "pathe": "^2.0.3" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/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==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/jiti": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", + "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "devOptional": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", + "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.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/multer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", + "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", + "object-assign": "^4.1.1", + "type-is": "^1.6.18", + "xtend": "^4.0.2" + }, + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/multer/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-addon-api": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz", + "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/nypm": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.1.tgz", + "integrity": "sha512-hlacBiRiv1k9hZFiphPUkfSQ/ZfQzZDzC+8z0wL3lvDAOUu/2NnChkKuMoMjNur/9OpKuz2QsIeiPVN0xM5Q0w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.2", + "pathe": "^2.0.3", + "pkg-types": "^2.2.0", + "tinyexec": "^1.0.1" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "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==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "license": "MIT", + "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-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", + "license": "MIT", + "dependencies": { + "jsonwebtoken": "^9.0.0", + "passport-strategy": "^1.0.0" + } + }, + "node_modules/passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "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-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/pkg-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, + "node_modules/prisma": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.15.0.tgz", + "integrity": "sha512-E6RCgOt+kUVtjtZgLQDBJ6md2tDItLJNExwI0XJeBc1FKL+Vwb+ovxXxuok9r8oBgsOXBA33fGDuE/0qDdCWqQ==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/config": "6.15.0", + "@prisma/engines": "6.15.0" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc9": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", + "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "defu": "^6.1.4", + "destr": "^2.0.3" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "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" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/tinyexec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "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==", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/zod": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.0.14.tgz", + "integrity": "sha512-nGFJTnJN6cM2v9kXL+SOBq3AtjQby3Mv5ySGFof5UGRHrRioSJ5iG680cYNjE/yWk671nROcpPj4hAS8nyLhSw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/mission4/package.json b/mission4/package.json new file mode 100644 index 000000000..83aa092d8 --- /dev/null +++ b/mission4/package.json @@ -0,0 +1,32 @@ +{ + "name": "mission3", + "version": "1.0.0", + "main": "index.js", + "type": "module", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node src/app.js" + }, + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "@prisma/client": "^6.13.0", + "bcrypt": "^6.0.0", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^17.2.2", + "express": "^5.1.0", + "multer": "^2.0.2", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", + "passport-local": "^1.0.0", + "zod": "^4.0.14" + }, + "devDependencies": { + "prisma": "^6.15.0" + }, + "prisma": { + "seed": "node prisma/seed.js" + } +} diff --git a/mission4/prisma/migrations/20250904083711_test/migration.sql b/mission4/prisma/migrations/20250904083711_test/migration.sql new file mode 100644 index 000000000..ad7fbdc5d --- /dev/null +++ b/mission4/prisma/migrations/20250904083711_test/migration.sql @@ -0,0 +1,94 @@ +-- CreateTable +CREATE TABLE "public"."User" ( + "id" SERIAL NOT NULL, + "email" TEXT NOT NULL, + "nickname" TEXT NOT NULL, + "image" TEXT, + "password" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Product" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT NOT NULL, + "price" INTEGER NOT NULL, + "tags" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Product_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Article" ( + "id" SERIAL NOT NULL, + "title" TEXT NOT NULL, + "content" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Article_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Comment" ( + "id" SERIAL NOT NULL, + "content" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "productId" INTEGER, + "articleId" INTEGER, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Comment_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Like" ( + "id" SERIAL NOT NULL, + "like" BOOLEAN NOT NULL DEFAULT true, + "userId" INTEGER NOT NULL, + "productId" INTEGER, + "articleId" INTEGER, + + CONSTRAINT "Like_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "public"."User"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "Like_userId_productId_key" ON "public"."Like"("userId", "productId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Like_userId_articleId_key" ON "public"."Like"("userId", "articleId"); + +-- AddForeignKey +ALTER TABLE "public"."Product" ADD CONSTRAINT "Product_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Article" ADD CONSTRAINT "Article_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_productId_fkey" FOREIGN KEY ("productId") REFERENCES "public"."Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "public"."Article"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_productId_fkey" FOREIGN KEY ("productId") REFERENCES "public"."Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "public"."Article"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/mission4/prisma/migrations/migration_lock.toml b/mission4/prisma/migrations/migration_lock.toml new file mode 100644 index 000000000..044d57cdb --- /dev/null +++ b/mission4/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (e.g., Git) +provider = "postgresql" diff --git a/mission4/prisma/schema.prisma b/mission4/prisma/schema.prisma new file mode 100644 index 000000000..3fde3edd3 --- /dev/null +++ b/mission4/prisma/schema.prisma @@ -0,0 +1,75 @@ +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" +} + +model User { + id Int @id @default(autoincrement()) + email String @unique + nickname String + image String? + password String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + article Article[] + product Product[] + comment Comment[] + like Like[] +} + +model Product { + id Int @id @default(autoincrement()) + name String + description String + price Int + tags String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + comment Comment[] + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + like Like[] +} + +model Article { + id Int @id @default(autoincrement()) + title String + content String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + comment Comment[] + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + like Like[] +} + +model Comment { + id Int @id @default(autoincrement()) + content String + createdAt DateTime @default(now()) + productId Int? + product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) + articleId Int? + article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) +} + +model Like { + id Int @id @default(autoincrement()) + like Boolean @default(true) + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + productId Int? + product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) + articleId Int? + article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) + + // 유저-상품, 유저-게시글 각각 중복 방지 + @@unique([userId, productId]) + @@unique([userId, articleId]) +} \ No newline at end of file diff --git a/mission4/src/app.js b/mission4/src/app.js new file mode 100644 index 000000000..5922f05c3 --- /dev/null +++ b/mission4/src/app.js @@ -0,0 +1,36 @@ +import express from 'express'; +import cookieParser from 'cookie-parser'; +import router from './routers/index.js'; +import { PORT } from './lib/constants.js'; +import passport from './lib/passport/index.js'; +import multer from 'multer'; +import cors from 'cors'; + +const app = express(); + +app.use(express.urlencoded({ extended: true })); + +app.use(cookieParser()); +app.use(express.json()); +app.use(passport.initialize()); +app.use(router); + +const upload = multer({ dest: 'uploads/'}) // multer를 통해 업로드된 사진이 저장될 폴더 + +app.post('/photos', upload.single('image'), (req, res) => { // ./photo라는 경로에서 ./uploads/에 있는 파일을 서빙 + const path = 'download/' + req.file.filename; + res.json({ path }); // 업로드 됬을 시, 사진의 저장된 위치를 알려줌으로써 확인 가능 +}); + +app.use('/downlaod', express.static('uploads')); + +const corsOptions = { //CORS 설정 및 whitelist로 'http://localhost:3000'을 설정 + origin: 'http://localhost:3000', + optionSuccessStatus: 200 +} + +app.use(cors(corsOptions)); + +app.listen(PORT, () => { + console.log(`Server is running on http://localhost:${PORT}`); +}); diff --git a/mission4/src/lib/constants.js b/mission4/src/lib/constants.js new file mode 100644 index 000000000..af8e48a99 --- /dev/null +++ b/mission4/src/lib/constants.js @@ -0,0 +1,21 @@ +import dotenv from 'dotenv'; + +dotenv.config(); + +const NODE_ENV = process.env.NODE_ENV || 'development'; +const PORT = process.env.PORT || 3000; +const JWT_ACCESS_TOKEN_SECRET = + process.env.JWT_ACCESS_TOKEN_SECRET || 'your_jwt_access_token_secret'; +const JWT_REFRESH_TOKEN_SECRET = + process.env.JWT_REFRESH_TOKEN_SECRET || 'your_jwt_refresh_token_secret'; +const ACCESS_TOKEN_COOKIE_NAME = 'access-token'; +const REFRESH_TOKEN_COOKIE_NAME = 'refresh-token'; + +export { + NODE_ENV, + PORT, + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, + ACCESS_TOKEN_COOKIE_NAME, + REFRESH_TOKEN_COOKIE_NAME, +}; diff --git a/mission4/src/lib/passport/index.js b/mission4/src/lib/passport/index.js new file mode 100644 index 000000000..fb58a8840 --- /dev/null +++ b/mission4/src/lib/passport/index.js @@ -0,0 +1,10 @@ +import passport from 'passport'; +import prisma from '../prisma.js'; +import { localStrategy } from './localStrategy.js'; +import { accessTokenStrategy, refreshTokenStrategy } from './jwtStrategy.js'; + +passport.use('local', localStrategy); +passport.use('access-token', accessTokenStrategy); +passport.use('refresh-token', refreshTokenStrategy); + +export default passport; diff --git a/mission4/src/lib/passport/jwtStrategy.js b/mission4/src/lib/passport/jwtStrategy.js new file mode 100644 index 000000000..f6b16b4f0 --- /dev/null +++ b/mission4/src/lib/passport/jwtStrategy.js @@ -0,0 +1,39 @@ +import { Strategy as JwtStrategy } from 'passport-jwt'; +import prisma from '../prisma.js'; +import { + ACCESS_TOKEN_COOKIE_NAME, + REFRESH_TOKEN_COOKIE_NAME, + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, +} from '../constants.js'; + +const accessTokenOptions = { + jwtFromRequest: (req) => req.cookies[ACCESS_TOKEN_COOKIE_NAME], + secretOrKey: JWT_ACCESS_TOKEN_SECRET, +}; + +const refreshTokenOptions = { + jwtFromRequest: (req) => req.cookies[REFRESH_TOKEN_COOKIE_NAME], + secretOrKey: JWT_REFRESH_TOKEN_SECRET, +}; + +async function jwtVerify(payload, done) { + try { + const user = await prisma.user.findUnique({ + where: { id: payload.sub }, + }); + done(null, user); + } catch (error) { + done(error, false); + } +} + +export const accessTokenStrategy = new JwtStrategy( + accessTokenOptions, + jwtVerify +); + +export const refreshTokenStrategy = new JwtStrategy( + refreshTokenOptions, + jwtVerify +); diff --git a/mission4/src/lib/passport/localStrategy.js b/mission4/src/lib/passport/localStrategy.js new file mode 100644 index 000000000..5602440e2 --- /dev/null +++ b/mission4/src/lib/passport/localStrategy.js @@ -0,0 +1,27 @@ +import { Strategy as LocalStrategy } from 'passport-local'; +import bcrypt from 'bcrypt'; +import prisma from '../prisma.js'; + +export const localStrategy = new LocalStrategy( + { + usernameField: 'email', // 👈 email을 username 대신 쓰도록 지정 + passwordField: 'password', // (기본값이라 안 써도 되지만 명시하면 좋음) + }, + async (email, password, done) => { + try { + const user = await prisma.user.findUnique({ where: { email } }); + if (!user) { + return done(null, false, { message: 'No user found' }); + } + + const isPasswordValid = await bcrypt.compare(password, user.password); + if (!isPasswordValid) { + return done(null, false, { message: 'Invalid password' }); + } + + return done(null, user); // 👈 user 객체에 id 꼭 있어야 함 + } catch (err) { + return done(err); + } + } +); \ No newline at end of file diff --git a/mission4/src/lib/prisma.js b/mission4/src/lib/prisma.js new file mode 100644 index 000000000..b904402d2 --- /dev/null +++ b/mission4/src/lib/prisma.js @@ -0,0 +1,5 @@ +import { PrismaClient } from '@prisma/client'; + +const prisma = new PrismaClient(); + +export default prisma; \ No newline at end of file diff --git a/mission4/src/lib/token.js b/mission4/src/lib/token.js new file mode 100644 index 000000000..650066e17 --- /dev/null +++ b/mission4/src/lib/token.js @@ -0,0 +1,27 @@ +import jwt from 'jsonwebtoken'; +import { + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, +} from './constants.js'; + +function generateTokens(userId) { + const accessToken = jwt.sign({ sub: userId }, JWT_ACCESS_TOKEN_SECRET, { + expiresIn: '1h', + }); + const refreshToken = jwt.sign({ sub: userId }, JWT_REFRESH_TOKEN_SECRET, { + expiresIn: '1d', + }); + return { accessToken, refreshToken }; +} + +function verifyAccessToken(token) { + const decoded = jwt.verify(token, JWT_ACCESS_TOKEN_SECRET); + return { userId: decoded.sub }; +} + +function verifyRefreshToken(token) { + const decoded = jwt.verify(token, JWT_REFRESH_TOKEN_SECRET); + return { userId: decoded.sub }; +} + +export { generateTokens, verifyAccessToken, verifyRefreshToken }; diff --git a/mission4/src/routers/articleRouter.js b/mission4/src/routers/articleRouter.js new file mode 100644 index 000000000..15235f2ee --- /dev/null +++ b/mission4/src/routers/articleRouter.js @@ -0,0 +1,178 @@ +import express from 'express'; +import prisma from '../lib/prisma.js'; +import passport from '../lib/passport/index.js'; +import { z } from 'zod'; + +const router = express.Router(); + +const schema = z.object({ //유효성 검사 설정하기 + title: z.string().min(1, { message: "제목을 입력해주세요" }), + content: z.string().min(10, { message: "내용은 최소 10자 이상이어야 합니다." }).max(200, { message: "내용은 최대 200자까지 가능합니다." }), +}); + +router.post( + '/aritlces', + passport.authenticate('access-token', { session: false }), + createArticle +); +router.get('/', getArticles); +router.patch( + '/aritlces/:id', + passport.authenticate('access-token', { session: false }), + modifyArticle +); +router.delete('/aritlces/:id', + passport.authenticate('local', { session: false }), + deleteArticle +); +router.get('/aritlces/:id', + passport.authenticate('access-token', { session: false }), + getDetailArticle +); + +async function createArticle(req, res, next) { +try { + const user = req.user; + const validatedData = schema.parse(req.body); + const article = await prisma.article.create({ + data: { + title: validatedData.title, + content: validatedData.content, + userId: user.id + }, + }); + + return res.status(201).json(article); + } catch (err) { + next(err); + } +} + +async function getArticles(req, res, next) { + try { + const page = parseInt(req.query.page) || 1; + const keyword = req.query.keyword || ''; + const where = keyword //title과 content 에서 원하는 keyword가 있는 데이터를 찾도록 만든 변수 + ? { + OR: [ + { + title: { + contains: keyword, + mode: 'insensitive', //대소문자 구분 없이 검색하기 위해 + }, + }, + { + content: { + contains: keyword, + mode: 'insensitive', + }, + }, + ], + } + : {}; //기본값 {}으로 빈 객체를 수식하기 위함 + + const articles = await prisma.article.findMany({ + skip: (page - 1) * 5, //offset pagination + take: 5, + orderBy: { // 최신 순서대로 정렬하기(최신순) + createdAt: 'desc', + }, + select: { + id: true, + title: true, + content: true, + createdAt: true, + }, + where, + }); + + res.status(200).json(articles); + } catch (error) { + next(err); + } +} + +async function modifyArticle(req, res, next) { + const articleId = Number(req.params.id); + const validatedData = schema.parse(req.body); + const user = req.user; + const check = await prisma.article.findUnique({ + where: { id: articleId } + }); + + if (user.Id !== check.userId) { + return res.status(404).json({ message: 'User not matched'}) + } + + try { + const updated = await prisma.article.update({ + where: { id: articleId }, + data: { + title: validatedData.title, + content: validatedData.content, + }, + }); + res.status(200).json(updated); + } catch (err) { + next(err); + } +} + +async function deleteArticle(req, res, next) { + const articleId = Number(req.params.id); + const user = req.user; + const check = await prisma.article.findUnique({ + where: { id: articleId } + }); + + if (user.Id !== check.userId) { + return res.status(404).json({ message: 'User not matched'}) + } + + try { + await prisma.article.delete({ + where: { id: articleId }, + }); + res.status(204).end(); + } catch (err) { + next(err); + } +} + +async function getDetailArticle(req, res, next) { + const articleId = Number(req.params.id); + + try { + const article = await prisma.article.findUnique({ + where: { id: articleId }, + select: { + id: true, + title: true, + content: true, + createdAt: true, + }, + }); + if (!article) { + return res.status(404).json({ error: 'Article not found'}); + } + res.status(200).json(article); + } catch (err) { + next(err); + } +} + + router.use((err, req, res, next) => { //에러 미드웨어 설정 + if (err instanceof z.ZodError) { + return res.status(400).json({ error: err.errors }); + } + + if (err.code === 'P2025') { + return res.status(404).json({ error: 'Record not found' }); + } + + console.error('unhandled Error:', err); + return res.status(500).json({ error: 'Internal Server Error' }); + }); + + +export default router; \ No newline at end of file diff --git a/mission4/src/routers/commentRouter.js b/mission4/src/routers/commentRouter.js new file mode 100644 index 000000000..ba7ff1699 --- /dev/null +++ b/mission4/src/routers/commentRouter.js @@ -0,0 +1,187 @@ +import express from 'express'; +import prisma from '../lib/prisma.js'; +import passport from '../lib/passport/index.js'; + +const router = express.Router(); + +router.post( + '/comments/products/:id', + passport.authenticate('access-token', { session: false }), + createProductComment +); +router.post( + '/comments/articles/:id', + passport.authenticate('access-token', { session: false }), + createArticleComment +); +router.patch('/comments/:id', modifyComment); +router.patch('/comments/:id', deleteComment); +router.get( + '/comments/products', + passport.authenticate('access-token', { session: false }), + productCommentList +); +router.get( + '/comments/articles', + passport.authenticate('access-token', { session: false }), + articleCommentList +); + +async function createProductComment(req, res, next) { + const productId = Number(req.params.id); + const { content } = req.body; + const user = req.user; + + try { + const comment = await prisma.comment.create({ + data: { + content, + productId, + articleId: null, + userId: user.id + } + }); + + res.status(201).json(comment); + } catch (err) { + next(err); + } +}; + +async function createArticleComment(req, res, next) { + const articleId = Number(req.params.id); + const { content } = req.body; + const user = req.user; + + try { + const comment = await prisma.comment.create({ + data: { + content, + productId: null, + articleId, + userId: user.id + } + }); + + res.status(201).json(comment); + } catch (err) { + next(err); + } +}; + +async function modifyComment(req, res, next) { + const commentId = Number(req.params.id); + const { content } = req.body; + const user = req.user; + const check = await prisma.comment.findUnique({ + where: { id: commentId } + }); + + if (user.id !== check.userId) { + return res.status(404).json({ message: 'User not matched'}) + } + + try { + const updated = await prisma.comment.update({ + where: { id: commentId }, + data: { + content, + }, + }); + res.status(201).json(updated); + } catch (err) { + next(err); + } +}; + +async function deleteComment(req, res) { + const commentId = Number(req.params.id); + const user = req.user; + const check = await prisma.comment.findUnique({ + where: { id: commentId } + }); + + if (user.id !== check.userId) { + return res.status(404).json({ message: 'User not matched'}) + } + + try { + await prisma.comment.delete({ + where: { id: commentId }, + }); + + res.status(204).end(); + } catch (err) { + next(err); + } +}; + +async function productCommentList(req, res, next) { + const productId = parseInt(req.query.id) || 1; + const lastId = req.query.lastId ? parseInt(req.query.lastId) : null; //cursor 방식의 pagination을 하기 위한 lastId 상수 지정 + try { + const comments = await prisma.comment.findMany({ + where: { //article이 아니고 product의 comment를 골라내기 위해 만든 함수 + AND: [ + { + articleId: null + },{ + productId + }, + ], + }, + take: 5, //첫 불러내는 comment가 총 5개 이고 lastId가 지정이 안되면 skip 의 값은 0이 되고 있다면 1로 설정 + skip: lastId ? 1: 0, + ...(lastId && { cursor: { id: lastId } }), //lastId의 값이 있을때 괄호가 풀어지며 내부의 'cursor: { id: lastId }가 작동함 + select: { + id: true, + content: true, + createdAt: true, + }, + }); + + res.status(200).json(comments); + } catch (err) { + next(err); + } +}; + +async function articleCommentList(req, res, next) { + const articleId = parseInt(req.query.id) || 1; + const lastId = req.query.lastId ? parseInt(req.query.lastId) : null; + try { + const comments = await prisma.comment.findMany({ + where: { //위와 반대로 product이 아니고 article의 comment를 골라내기 위해 만든 함수 + AND: [ + { + articleId + },{ + productId: null + }, + ], + }, + take: 5, + skip: lastId ? 1: 0, + ...(lastId && { cursor: { id: lastId } }), + select: { + id: true, + content: true, + createdAt: true, + }, + }); + res.status(201).json(comments); + } catch (err) { + next(err); + } +}; + + router.use((err, req, res, next) => { //에러 미드웨어 설정 + if (err.code === 'P2025') { + return res.status(404).json({ error: 'Record not found' }); + } + + console.error('unhandled Error:', err); + return res.status(500).json({ error: 'Internal Server Error' }); + }); + +export default router; diff --git a/mission4/src/routers/index.js b/mission4/src/routers/index.js new file mode 100644 index 000000000..47ec55ea5 --- /dev/null +++ b/mission4/src/routers/index.js @@ -0,0 +1,16 @@ +import express from 'express'; +import userRouter from './userRouter.js'; +import articleRouter from './articleRouter.js'; +import productRouter from './productRouter.js'; +import commentRouter from './commentRouter.js'; +import likeRouter from './likeRouter.js'; + +const router = express.Router(); + +router.use(userRouter); +router.use(articleRouter); +router.use(productRouter); +router.use(commentRouter); +router.use(likeRouter) + +export default router; \ No newline at end of file diff --git a/mission4/src/routers/likeRouter.js b/mission4/src/routers/likeRouter.js new file mode 100644 index 000000000..4e302099b --- /dev/null +++ b/mission4/src/routers/likeRouter.js @@ -0,0 +1,188 @@ +import express from 'express'; +import prisma from '../lib/prisma.js'; +import passport from '../lib/passport/index.js'; + +const router = express.Router(); + +router.post( + '/like/articles/:id', + passport.authenticate('access-token', { session: false }), + likeArticle +); +router.post( + '/like/products/:id', + passport.authenticate('access-token', { session: false }), + likeProduct +); +router.get( + '/like/articles/:id', + passport.authenticate('access-token', { session: false }), + getArticles +); +router.get( + '/like/products/:id', + passport.authenticate('access-token', { session: false }), + getProducts +); + + +async function likeArticle(req, res, next) { + const user = req.user; + const articleId = Number(req.params.id); + + try { + const existing = await prisma.like.findUnique({ + where: { + user_articleId: { + userId: user.id, + articleId, + }, + }, + }); + + if (existing) { + const updated = await prisma.like.update({ + where: { + userId_articleId: { + userId: user.id, + articleId, + }, + }, + data: { + like: !existing.like, + }, + }); + return res.status(200).json({ message: 'Like toggled', isliked: updated.like }); + } else { + const created = await prisma.like.create({ + data: { + like: true, + articleId, + userId: user.id, + }, + }); + return res.status(201).json({ message: 'Liked successfully', like: created.like }); + } + } catch(err) { + next(err); + } +} + +async function likeProduct(req, res, next) { + const user = req.user; + const productId = Number(req.params.id); + + try { + const existing = await prisma.like.findUnique({ + where: { + user_productId: { + userId: user.id, + productId, + }, + }, + }); + + if (existing) { + const updated = await prisma.like.update({ + where: { + userId_productId: { + userId: user.id, + productId, + }, + }, + data: { + like: !existing.like, + }, + }); + return res.status(200).json({ message: 'Like toggled', isLiked: updated.like }); + } else { + const created = await prisma.like.create({ + data: { + like: true, + productId, + userId: user.id, + }, + }); + return res.status(201).json({ message: 'Liked successfully', isLiked: created.like }); + } + } catch(err) { + next(err); + } +} + +async function getProducts(req, res, next) { + const user = req.user; + const productId = Number(req.params.id); + + try { + const product = await prisma.product.findUnique({ + where: { id: productId }, + select: { + id: true, + name: true, + price: true, + tags: true + } + }); + + if (!product) { + return res.status(404).json({ message: 'Product not found' }); + } + + // 좋아요 여부 확인 + const like = await prisma.like.findUnique({ + where: { + userId_productId: { + userId: user.id, + productId, + }, + }, + }); + + res.json({ + ...product, + isLiked: like ? like.like : false, + }); + } catch (err) { + next(err); + } + } + + async function getArticles(req, res, next) { + const user = req.user; + const articleId = Number(req.params.id); + + try { + const article = await prisma.article.findUnique({ + where: { id: articleId }, + select: { + id: true, + name: true, + price: true, + tags: true + } + }); + + if (!article) { + return res.status(404).json({ message: 'Article not found' }); + } + + const like = await prisma.like.findUnique({ + where: { + userId_articleId: { + userId: user.id, + articleId, + }, + }, + }); + + res.json({ + ...article, + isLiked: like ? like.like : false, + }); + } catch (err) { + next(err); + } + } + +export default router; \ No newline at end of file diff --git a/mission4/src/routers/productRouter.js b/mission4/src/routers/productRouter.js new file mode 100644 index 000000000..88b7d9132 --- /dev/null +++ b/mission4/src/routers/productRouter.js @@ -0,0 +1,188 @@ +import express from 'express'; +import prisma from '../lib/prisma.js'; +import passport from '../lib/passport/index.js'; +import { z } from 'zod'; + +const router = express.Router(); + +const schema = z.object({ //유효성 검사 설정하기 + name: z.string().min(1, { message: "이름을 입력해주세요" }), + description: z.string().min(10, { message: "설명은 최소 10자 이상이어야 합니다." }).max(100, { message: "설명은 최대 100자까지 가능합니다." }), + price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }), + tags: z.string().min(1, { message: "태그는 한개 이상이여야 합니다" }), +}); + +router.post( + '/products', + passport.authenticate('access-token', { session: false }), + createProduct +); +router.get('/products', getProducts); +router.patch( + '/products/:id', + passport.authenticate('access-token', { session: false }), + modifyProduct +); +router.delete('/products/:id', + passport.authenticate('local', { session: false }), + deleteProduct +); +router.get('/products/:id', + passport.authenticate('access-token', { session: false }), + getDetailProduct +); + +async function createProduct(req, res, next) { +try { + const validatedData = schema.parse(req.body); + const user = req.user; + const product = await prisma.product.create ({ + data: { + name: validatedData.name, + description: validatedData.description, + price: validatedData.price, + tags: validatedData.tags, + userId: user.id + }, + }); + + return res.status(201).json(product); + } catch (err) { + next(err); + } +} + +async function getProducts(req, res, next) { +try { + const page = parseInt(req.query.page) || 1; //값이 없을 경우도 수식하기 위함 + const keyword = req.query.keyword ? decodeURIComponent(req.query.keyword) : ''; + const where = keyword //name과 description에서 원하는 keyword가 들어간 데이터를 찾도록 만든 변수 + ? { + OR: [ + { + name: { + contains: keyword, + mode: 'insensitive', //대소문자 구분 없이 검색하기 위해 + }, + }, + { + description: { + contains: keyword, + mode: 'insensitive', + }, + }, + ], + } + : {}; //기본값 {}으로 빈 객체를 수식하기 위함 + + const products = await prisma.product.findMany({ + skip: (page - 1) * 5, + take: 5, + orderBy: { // 최신 순서대로 정렬하기(최신순) + createdAt: 'desc', + }, + select: { + id: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + where, + }); + + res.status(200).json(products); + } catch (err) { + next(err); + } +} + +async function modifyProduct(req, res, next) { + const productId = Number(req.params.id); + const validatedData = schema.parse(req.body); + const user = req.user; + const check = await prisma.product.findUnique({ + where: { id: productId } + }); + + if (user.Id !== check.userId) { + return res.status(404).json({ message: 'User not matched'}) + } + + try{ + const updated = await prisma.product.update({ + where: { id: productId }, + data: { + name: validatedData.name, + description: validatedData.description, + price: validatedData.price, + tags: validatedData.tags, + }, + }); + res.status(201).json(updated); + } catch (err) { + next(err); + } +} + +async function deleteProduct(req, res, next) { + const productId = Number(req.params.id); + const user = req.user; + const check = await prisma.product.findUnique({ + where: { id: productId } + }); + + if (user.Id !== check.userId) { + return res.status(404).json({ message: 'User not matched'}) + } + + try { + await prisma.product.delete({ + where: { id: productId }, + }); + res.status(204).end(); + } catch (err) { + next(err); + } +} + +async function getDetailProduct(req, res, next) { + const productId = Number(req.params.id); + + try { + const product = await prisma.product.findUnique({ + where: { id: productId }, + select: { + id: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + }); + if (!product) { + return res.status(404).json({ error: 'Product not found'}); + } + res.status(200).json(product); + } catch (err) { + next(err); + } +} + + router.use((err, req, res, next) => { //에러 미드웨어 설정 + if (err instanceof z.ZodError) { + return res.status(400).json({ error: err.errors }); + } + + if (err.code === 'P2025') { + return res.status(404).json({ error: 'Record not found' }); + } + + console.error('unhandled Error:', err); + return res.status(500).json({ error: 'Internal Server Error' }); + }); + + +export default router; diff --git a/mission4/src/routers/userRouter.js b/mission4/src/routers/userRouter.js new file mode 100644 index 000000000..ea7b101d4 --- /dev/null +++ b/mission4/src/routers/userRouter.js @@ -0,0 +1,209 @@ +import express from 'express'; +import bcrypt from 'bcrypt'; +import prisma from '../lib/prisma.js'; +import passport from '../lib/passport/index.js'; +import { generateTokens } from '../lib/token.js'; +import { + NODE_ENV, + ACCESS_TOKEN_COOKIE_NAME, + REFRESH_TOKEN_COOKIE_NAME, +} from '../lib/constants.js'; + +const router = express.Router(); + +router.post('/users/register', register); +router.post('/users/login', + passport.authenticate('local', { session: false }), + login +); +router.get('/users/profile', + passport.authenticate('access-token', { session: false }), + profile +); +router.patch( + '/users/modifyInformation', + passport.authenticate('access-token', { session: false }), + modifyinformation +); +router.patch( + '/users/modifyPassword', + passport.authenticate('access-token', { session: false }), + modifyPassword +); +router.get( + '/users/products', + passport.authenticate('access-token', { session: false }), + products +); +router.post( + '/users/refresh', + passport.authenticate('refresh-token', { session: false }), + refreshTokens +); +router.post('/users/logout', logout); + +async function register(req, res, next) { + const { email, nickname, password } = req.body; + + try{ + const check = await prisma.user.findUnique({ where: { email } }); + if (check) { + return res.status(409).json({ message: 'This ID already exists' }); + } + + const salt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(password, salt); + const user = await prisma.user.create({ + data: { email, nickname, password: hashedPassword }, + }); + + res.status(201).json({ "message": "User registered successfully" }); +} catch(err) { + next(err); +} +} + +function login(req, res, next) { + if(!req.user) { + return res.status(401).json({ message: 'Unauthorized' }) + } + + try{ + const { accessToken, refreshToken } = generateTokens(req.user.id); + setTokenCookies(res, accessToken, refreshToken); + res.status(200).json({ "token": accessToken }); + } catch(err) { + next(err); + } +} + +async function profile(req, res, next) { + const user = req.user; + try { + const profile = await prisma.user.findUnique({ + where: { + id: user.id + }, + select: { + id: true, + email: true, + nickname: true, + image: true, + createdAt: true + } + }); + res.status(200).json(profile); + } catch(err) { + next(err); + } +}; + +async function modifyinformation(req, res, next) { + const user = req.user; + const { nickname, image } = req.body; + + try{ + const updateData = {}; + if (nickname) updateData.nickname = nickname; + if (image) updateData.image = image; + + if (Object.keys(updateData).length === 0) { + return res.status(400).json({ message: 'No update data provided' }) + } + + const updatedUser = await prisma.user.update({ + where: { id: user.id }, + data: updateData, + select: { + id: true, + email: true, + nickname: true, + image: true, + createdAt: true, + updateAt: true, + }, + }); + + res.status(200).json({ + message: 'User information updated successfully', + user: updatedUser, + }) + } catch(err) { + next(err); + } +} + +async function modifyPassword(req, res, next) { + const user = req.user; + const { password } = req.body; + + try{ + const salt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(password, salt); + + await prisma.user.update({ + where: { id: user.id }, + data: { + password: hashedPassword + }, + }); + + res.status(200).json({ message: 'User passowrd updated successfully'}); + } catch(err){ + next(err); + } +} + +async function products(req, res, nest) { + const user = req.user; + const products = await prisma.product.findMany({ + where: { + userId: user.id + }, + select: { + name: true, + description: true, + price: true, + tags: true + }, + }); + if (!products) { + return res.status(400).json({ message: "No product" }); + } + res.status(200).json(products); +} + +function logout(req, res) { + clearTokenCookies(res); + res.status(200).send({ message: 'Logged out successfully' }); +} + +async function refreshTokens(req, res) { + const user = req.user; + const { accessToken, refreshToken: newRefreshToken } = generateTokens( + user.id + ); + setTokenCookies(res, accessToken, newRefreshToken); + res.status(200).send({ message: 'Tokens refreshed' }); +} + +function setTokenCookies(res, accessToken, refreshToken) { + res.cookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, { + httpOnly: true, + secure: NODE_ENV === 'production', + maxAge: 1 * 60 * 60 * 1000, // 1 hour + }); + res.cookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken, { + httpOnly: true, + secure: NODE_ENV === 'production', + maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days + path: '/users/refresh', + }); +} + +function clearTokenCookies(res) { + res.clearCookie(ACCESS_TOKEN_COOKIE_NAME); + res.clearCookie(REFRESH_TOKEN_COOKIE_NAME); +} + +export default router; From 2cb5df5f4dcdbf27df912ca3ccbb80c876321b6e Mon Sep 17 00:00:00 2001 From: Batur-s Date: Thu, 4 Sep 2025 18:13:15 +0900 Subject: [PATCH 22/38] Refactor: refactoring photo upload --- mission4/src/app.js | 11 +-------- mission4/src/routers/index.js | 4 +++- mission4/src/routers/photoRouter.js | 36 +++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 mission4/src/routers/photoRouter.js diff --git a/mission4/src/app.js b/mission4/src/app.js index 5922f05c3..6b49f5e20 100644 --- a/mission4/src/app.js +++ b/mission4/src/app.js @@ -3,7 +3,6 @@ import cookieParser from 'cookie-parser'; import router from './routers/index.js'; import { PORT } from './lib/constants.js'; import passport from './lib/passport/index.js'; -import multer from 'multer'; import cors from 'cors'; const app = express(); @@ -14,15 +13,7 @@ app.use(cookieParser()); app.use(express.json()); app.use(passport.initialize()); app.use(router); - -const upload = multer({ dest: 'uploads/'}) // multer를 통해 업로드된 사진이 저장될 폴더 - -app.post('/photos', upload.single('image'), (req, res) => { // ./photo라는 경로에서 ./uploads/에 있는 파일을 서빙 - const path = 'download/' + req.file.filename; - res.json({ path }); // 업로드 됬을 시, 사진의 저장된 위치를 알려줌으로써 확인 가능 -}); - -app.use('/downlaod', express.static('uploads')); +app.use('/download', express.static('uploads')); const corsOptions = { //CORS 설정 및 whitelist로 'http://localhost:3000'을 설정 origin: 'http://localhost:3000', diff --git a/mission4/src/routers/index.js b/mission4/src/routers/index.js index 47ec55ea5..4fd844074 100644 --- a/mission4/src/routers/index.js +++ b/mission4/src/routers/index.js @@ -4,6 +4,7 @@ import articleRouter from './articleRouter.js'; import productRouter from './productRouter.js'; import commentRouter from './commentRouter.js'; import likeRouter from './likeRouter.js'; +import photoRouter from './photoRouter.js'; const router = express.Router(); @@ -11,6 +12,7 @@ router.use(userRouter); router.use(articleRouter); router.use(productRouter); router.use(commentRouter); -router.use(likeRouter) +router.use(likeRouter); +router.use(photoRouter); export default router; \ No newline at end of file diff --git a/mission4/src/routers/photoRouter.js b/mission4/src/routers/photoRouter.js new file mode 100644 index 000000000..9c9408ce3 --- /dev/null +++ b/mission4/src/routers/photoRouter.js @@ -0,0 +1,36 @@ +import express from 'express'; +import multer from 'multer'; +import passport from '../lib/passport/index.js'; +import prisma from '../lib/prisma.js'; + +const router = express.Router(); +const upload = multer({ dest: 'uploads/'}) + +router.post( + '/users/photos', + passport.authenticate('access-token', { session: false }), + upload.single('image'), + async(req, res, next) => { + const user = req.user; + + if (!req.file) { + return res.status(400).json({ message: 'No file upload' }); + } + + try{ + const imageUrl = `/download/${req.file.filename}`; + const updatedUser = await prisma.user.update({ + where: { id: user.id }, + data: { image: imageUrl }, + }); + + res.status(200).json({ + message: 'Photo uploaded successfully', + image: updatedUser.image, + }); + } catch (err) { + next(err); + } +}); + +export default router; \ No newline at end of file From 30f6fde16e75dd43c2fb60d3cc7ab397ae970739 Mon Sep 17 00:00:00 2001 From: Batur-s Date: Fri, 5 Sep 2025 15:49:19 +0900 Subject: [PATCH 23/38] =?UTF-8?q?feat:=20=EC=97=90=EB=9F=AC=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=ED=99=94,=20http-status=20=EB=B3=80=EA=B2=BD,=20zod?= =?UTF-8?q?=20=EC=A0=81=EA=B7=B9=EC=A0=81=20=EC=82=AC=EC=9A=A9,=20like=20?= =?UTF-8?q?=EC=A0=95=EC=83=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mission4/package-lock.json | 10 + mission4/package.json | 1 + mission4/prisma/schema.prisma | 2 +- mission4/src/app.js | 26 +- mission4/src/lib/passport/localStrategy.js | 18 +- mission4/src/middlewares/errorHandler.js | 17 ++ mission4/src/routers/articleRouter.js | 300 ++++++++++--------- mission4/src/routers/commentRouter.js | 283 ++++++++++-------- mission4/src/routers/likeRouter.js | 314 ++++++++++---------- mission4/src/routers/photoRouter.js | 50 ++-- mission4/src/routers/productRouter.js | 321 +++++++++++---------- mission4/src/routers/userRouter.js | 171 ++++++----- 12 files changed, 833 insertions(+), 680 deletions(-) create mode 100644 mission4/src/middlewares/errorHandler.js diff --git a/mission4/package-lock.json b/mission4/package-lock.json index 55d43f241..ceacb6d29 100644 --- a/mission4/package-lock.json +++ b/mission4/package-lock.json @@ -15,6 +15,7 @@ "cors": "^2.8.5", "dotenv": "^17.2.2", "express": "^5.1.0", + "http-status": "^2.1.0", "multer": "^2.0.2", "passport": "^0.7.0", "passport-jwt": "^4.0.1", @@ -800,6 +801,15 @@ "node": ">= 0.8" } }, + "node_modules/http-status": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-status/-/http-status-2.1.0.tgz", + "integrity": "sha512-O5kPr7AW7wYd/BBiOezTwnVAnmSNFY+J7hlZD2X5IOxVBetjcHAiTXhzj0gMrnojQlwy+UT1/Y3H3vJ3UlmvLA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", diff --git a/mission4/package.json b/mission4/package.json index 83aa092d8..462ca47a9 100644 --- a/mission4/package.json +++ b/mission4/package.json @@ -17,6 +17,7 @@ "cors": "^2.8.5", "dotenv": "^17.2.2", "express": "^5.1.0", + "http-status": "^2.1.0", "multer": "^2.0.2", "passport": "^0.7.0", "passport-jwt": "^4.0.1", diff --git a/mission4/prisma/schema.prisma b/mission4/prisma/schema.prisma index 3fde3edd3..05365cc8e 100644 --- a/mission4/prisma/schema.prisma +++ b/mission4/prisma/schema.prisma @@ -69,7 +69,7 @@ model Like { articleId Int? article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) - // 유저-상품, 유저-게시글 각각 중복 방지 + // 유저-상품, 유저-게시글 각각 중복 방지, 좋아요 중첩 방지 @@unique([userId, productId]) @@unique([userId, articleId]) } \ No newline at end of file diff --git a/mission4/src/app.js b/mission4/src/app.js index 6b49f5e20..5e9dd5216 100644 --- a/mission4/src/app.js +++ b/mission4/src/app.js @@ -1,9 +1,10 @@ -import express from 'express'; -import cookieParser from 'cookie-parser'; -import router from './routers/index.js'; -import { PORT } from './lib/constants.js'; -import passport from './lib/passport/index.js'; -import cors from 'cors'; +import express from "express"; +import cookieParser from "cookie-parser"; +import router from "./routers/index.js"; +import { PORT } from "./lib/constants.js"; +import passport from "./lib/passport/index.js"; +import cors from "cors"; +import { errorHandler } from "./middlewares/errorHandler.js"; const app = express(); @@ -13,15 +14,18 @@ app.use(cookieParser()); app.use(express.json()); app.use(passport.initialize()); app.use(router); -app.use('/download', express.static('uploads')); +app.use("/download", express.static("uploads")); -const corsOptions = { //CORS 설정 및 whitelist로 'http://localhost:3000'을 설정 - origin: 'http://localhost:3000', - optionSuccessStatus: 200 -} +const corsOptions = { + //CORS 설정 및 whitelist로 'http://localhost:3000'을 설정 + origin: "http://localhost:3000", + optionSuccessStatus: 200, +}; app.use(cors(corsOptions)); +app.use(errorHandler); + app.listen(PORT, () => { console.log(`Server is running on http://localhost:${PORT}`); }); diff --git a/mission4/src/lib/passport/localStrategy.js b/mission4/src/lib/passport/localStrategy.js index 5602440e2..eceb1191d 100644 --- a/mission4/src/lib/passport/localStrategy.js +++ b/mission4/src/lib/passport/localStrategy.js @@ -1,27 +1,27 @@ -import { Strategy as LocalStrategy } from 'passport-local'; -import bcrypt from 'bcrypt'; -import prisma from '../prisma.js'; +import { Strategy as LocalStrategy } from "passport-local"; +import bcrypt from "bcrypt"; +import prisma from "../prisma.js"; export const localStrategy = new LocalStrategy( { - usernameField: 'email', // 👈 email을 username 대신 쓰도록 지정 - passwordField: 'password', // (기본값이라 안 써도 되지만 명시하면 좋음) + usernameField: "email", // email을 localStrategy의 고정값 'username' 대신 쓰도록 지정 + passwordField: "password", }, async (email, password, done) => { try { const user = await prisma.user.findUnique({ where: { email } }); if (!user) { - return done(null, false, { message: 'No user found' }); + return done(null, false, { message: "No user found" }); } const isPasswordValid = await bcrypt.compare(password, user.password); if (!isPasswordValid) { - return done(null, false, { message: 'Invalid password' }); + return done(null, false, { message: "Invalid password" }); } - return done(null, user); // 👈 user 객체에 id 꼭 있어야 함 + return done(null, user); } catch (err) { return done(err); } } -); \ No newline at end of file +); diff --git a/mission4/src/middlewares/errorHandler.js b/mission4/src/middlewares/errorHandler.js new file mode 100644 index 000000000..ce43d9ba8 --- /dev/null +++ b/mission4/src/middlewares/errorHandler.js @@ -0,0 +1,17 @@ +import { z } from "zod"; +import httpStatus from "http-status"; + +export function errorHandler(err, req, res, next) { + if (err instanceof z.ZodError) { + return res.status(httpStatus.BAD_REQUEST).json({ error: err.errors }); + } + + if (err.code === "P2025") { + return res.status(httpStatus.NOT_FOUND).json({ error: "Record not found" }); + } + + console.error("unhandled Error:", err); + return res + .status(httpStatus.INTERNAL_SERVER_ERROR) + .json({ error: "Internal Server Error" }); +} diff --git a/mission4/src/routers/articleRouter.js b/mission4/src/routers/articleRouter.js index 15235f2ee..6a00fbccd 100644 --- a/mission4/src/routers/articleRouter.js +++ b/mission4/src/routers/articleRouter.js @@ -1,178 +1,202 @@ -import express from 'express'; -import prisma from '../lib/prisma.js'; -import passport from '../lib/passport/index.js'; -import { z } from 'zod'; +import express from "express"; +import prisma from "../lib/prisma.js"; +import passport from "../lib/passport/index.js"; +import { z } from "zod"; +import status from "http-status"; const router = express.Router(); -const schema = z.object({ //유효성 검사 설정하기 - title: z.string().min(1, { message: "제목을 입력해주세요" }), - content: z.string().min(10, { message: "내용은 최소 10자 이상이어야 합니다." }).max(200, { message: "내용은 최대 200자까지 가능합니다." }), +// body 검증 (게시글 생성/수정) +const articleSchema = z.object({ + title: z.string().min(1, { message: "제목을 입력해주세요" }).optional(), + content: z + .string() + .min(10, { message: "내용은 최소 10자 이상이어야 합니다." }) + .max(200, { message: "내용은 최대 200자까지 가능합니다." }) + .optional() +}); + +// query 검증 (게시글 조회) +const articleQuerySchema = z.object({ + page: z + .string() + .optional() + .default("1") + .transform(Number) + .refine((val) => val > 0, { message: "page는 1 이상의 정수여야 합니다." }), + pageSize: z + .string() + .optional() + .default("5") + .transform(Number) + .refine((val) => val > 0 && val <= 100, { + message: "pageSize는 1~100 사이여야 합니다.", + }), + keyword: z.string().optional().default(""), }); router.post( - '/aritlces', - passport.authenticate('access-token', { session: false }), + "/articles", + passport.authenticate("access-token", { session: false }), createArticle ); -router.get('/', getArticles); +router.get("/articles", getArticles); router.patch( - '/aritlces/:id', - passport.authenticate('access-token', { session: false }), + "/articles/:id", + passport.authenticate("access-token", { session: false }), modifyArticle ); -router.delete('/aritlces/:id', - passport.authenticate('local', { session: false }), - deleteArticle +router.delete( + "/articles/:id", + passport.authenticate("access-token", { session: false }), + deleteArticle ); -router.get('/aritlces/:id', - passport.authenticate('access-token', { session: false }), - getDetailArticle +router.get( + "/articles/:id", + passport.authenticate("access-token", { session: false }), + getDetailArticle ); async function createArticle(req, res, next) { -try { - const user = req.user; - const validatedData = schema.parse(req.body); + const user = req.user; + const parsed = articleSchema.parse(req.body); + + try { const article = await prisma.article.create({ - data: { - title: validatedData.title, - content: validatedData.content, - userId: user.id - }, - }); + data: { + ...parsed, + userId: user.id, + }, + }); - return res.status(201).json(article); - } catch (err) { - next(err); - } + res.status(status.CREATED).json(article); + } catch (err) { + next(err); + } } async function getArticles(req, res, next) { - try { - const page = parseInt(req.query.page) || 1; - const keyword = req.query.keyword || ''; - const where = keyword //title과 content 에서 원하는 keyword가 있는 데이터를 찾도록 만든 변수 - ? { - OR: [ - { - title: { - contains: keyword, - mode: 'insensitive', //대소문자 구분 없이 검색하기 위해 - }, + const { page, pageSize, keyword } = articleQuerySchema.parse(req.query); + const where = keyword //title과 content 에서 원하는 keyword가 있는 데이터를 찾도록 만든 변수 + ? { + OR: [ + { + title: { + contains: keyword, + mode: "insensitive", //대소문자 구분 없이 검색하기 위해 }, - { - content: { - contains: keyword, - mode: 'insensitive', - }, + }, + { + content: { + contains: keyword, + mode: "insensitive", }, - ], - } - : {}; //기본값 {}으로 빈 객체를 수식하기 위함 - - const articles = await prisma.article.findMany({ - skip: (page - 1) * 5, //offset pagination - take: 5, - orderBy: { // 최신 순서대로 정렬하기(최신순) - createdAt: 'desc', - }, - select: { - id: true, - title: true, - content: true, - createdAt: true, - }, - where, - }); - - res.status(200).json(articles); - } catch (error) { - next(err); - } + }, + ], + } + : {}; //기본값 {}으로 빈 객체를 수식하기 위함 + + try { + const articles = await prisma.article.findMany({ + skip: (page - 1) * pageSize, //offset pagination + take: pageSize, + orderBy: { + // 최신 순서대로 정렬하기(최신순) + createdAt: "desc", + }, + select: { + id: true, + title: true, + content: true, + createdAt: true, + }, + where, + }); + + res.status(status.OK).json(articles); + } catch (error) { + next(err); + } } async function modifyArticle(req, res, next) { - const articleId = Number(req.params.id); - const validatedData = schema.parse(req.body); - const user = req.user; - const check = await prisma.article.findUnique({ - where: { id: articleId } + const articleId = Number(req.params.id); + const parsed = articleSchema.parse(req.body); + const user = req.user; + + try { + const article = await prisma.article.findUnique({ + where: { id: articleId }, }); - - if (user.Id !== check.userId) { - return res.status(404).json({ message: 'User not matched'}) - } - try { - const updated = await prisma.article.update({ - where: { id: articleId }, - data: { - title: validatedData.title, - content: validatedData.content, - }, - }); - res.status(200).json(updated); - } catch (err) { - next(err); + if (!article) { + return res + .status(status.NOT_FOUND) + .json({ message: "Article not found" }); + } + if (article.userId !== user.id) { + return res.status(status.FORBIDDEN).json({ message: "User not matched" }); } + + const updated = await prisma.article.update({ + where: { id: articleId }, + data: { + ...parsed, + }, + }); + res.status(status.OK).json(updated); + } catch (err) { + next(err); + } } async function deleteArticle(req, res, next) { - const articleId = Number(req.params.id); - const user = req.user; - const check = await prisma.article.findUnique({ - where: { id: articleId } + const articleId = Number(req.params.id); + const user = req.user; + + try { + const article = await prisma.article.findUnique({ + where: { id: articleId }, }); - - if (user.Id !== check.userId) { - return res.status(404).json({ message: 'User not matched'}) - } - try { - await prisma.article.delete({ - where: { id: articleId }, - }); - res.status(204).end(); - } catch (err) { - next(err); + if (!article) { + return res + .status(status.NOT_FOUND) + .json({ message: "Article not found" }); + } + if (article.userId !== user.id) { + return res.status(status.FORBIDDEN).json({ message: "User not matched" }); } + + await prisma.article.delete({ + where: { id: articleId }, + }); + res.status(status.NO_CONTENT).end(); + } catch (err) { + next(err); + } } async function getDetailArticle(req, res, next) { - const articleId = Number(req.params.id); - - try { - const article = await prisma.article.findUnique({ - where: { id: articleId }, - select: { - id: true, - title: true, - content: true, - createdAt: true, - }, - }); - if (!article) { - return res.status(404).json({ error: 'Article not found'}); - } - res.status(200).json(article); - } catch (err) { - next(err); + const articleId = Number(req.params.id); + + try { + const article = await prisma.article.findUnique({ + where: { id: articleId }, + select: { + id: true, + title: true, + content: true, + createdAt: true, + }, + }); + if (!article) { + return res.status(status.NOT_FOUND).json({ error: "Article not found" }); } + res.status(status.OK).json(article); + } catch (err) { + next(err); + } } - router.use((err, req, res, next) => { //에러 미드웨어 설정 - if (err instanceof z.ZodError) { - return res.status(400).json({ error: err.errors }); - } - - if (err.code === 'P2025') { - return res.status(404).json({ error: 'Record not found' }); - } - - console.error('unhandled Error:', err); - return res.status(500).json({ error: 'Internal Server Error' }); - }); - - -export default router; \ No newline at end of file +export default router; diff --git a/mission4/src/routers/commentRouter.js b/mission4/src/routers/commentRouter.js index ba7ff1699..071752946 100644 --- a/mission4/src/routers/commentRouter.js +++ b/mission4/src/routers/commentRouter.js @@ -1,187 +1,224 @@ -import express from 'express'; -import prisma from '../lib/prisma.js'; -import passport from '../lib/passport/index.js'; +import express from "express"; +import prisma from "../lib/prisma.js"; +import passport from "../lib/passport/index.js"; +import { z } from "zod"; +import status from "http-status"; const router = express.Router(); +// body 검증 (댓글 생성/수정) +const commentSchema = z.object({ + content: z + .string() + .min(5, { message: "덧글은 최소 5자 이상이어야 합니다." }) + .max(100, { message: "덧글은 최대 100자까지 가능합니다." }), +}); + +const commentQuerySchema = z.object({ + id: z + .string() + .regex(/^\d+$/, { message: "id는 숫자여야 합니다." }) + .transform(Number), + lastId: z + .string() + .regex(/^\d+$/, { message: "lastId는 숫자여야 합니다." }) + .transform(Number) + .optional(), +}); + router.post( - '/comments/products/:id', - passport.authenticate('access-token', { session: false }), + "/comments/products/:id", + passport.authenticate("access-token", { session: false }), createProductComment ); router.post( - '/comments/articles/:id', - passport.authenticate('access-token', { session: false }), + "/comments/articles/:id", + passport.authenticate("access-token", { session: false }), createArticleComment ); -router.patch('/comments/:id', modifyComment); -router.patch('/comments/:id', deleteComment); +router.patch( + "/comments/:id", + passport.authenticate("access-token", { session: false }), + modifyComment +); +router.delete( + "/comments/:id", + passport.authenticate("access-token", { session: false }), + deleteComment +); router.get( - '/comments/products', - passport.authenticate('access-token', { session: false }), + "/comments/products", + passport.authenticate("access-token", { session: false }), productCommentList ); router.get( - '/comments/articles', - passport.authenticate('access-token', { session: false }), + "/comments/articles", + passport.authenticate("access-token", { session: false }), articleCommentList ); async function createProductComment(req, res, next) { - const productId = Number(req.params.id); - const { content } = req.body; - const user = req.user; - - try { - const comment = await prisma.comment.create({ - data: { - content, + const productId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const user = req.user; + + try { + const comment = await prisma.comment.create({ + data: { + ...parsed, productId, articleId: null, - userId: user.id - } - }); + userId: user.id, + }, + }); - res.status(201).json(comment); - } catch (err) { - next(err); - } -}; + res.status(status.CREATED).json(comment); + } catch (err) { + next(err); + } +} async function createArticleComment(req, res, next) { - const articleId = Number(req.params.id); - const { content } = req.body; - const user = req.user; - - try { - const comment = await prisma.comment.create({ - data: { - content, + const articleId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const user = req.user; + + try { + const comment = await prisma.comment.create({ + data: { + ...parsed, productId: null, articleId, - userId: user.id - } - }); + userId: user.id, + }, + }); - res.status(201).json(comment); - } catch (err) { - next(err); - } -}; + res.status(status.CREATED).json(comment); + } catch (err) { + next(err); + } +} async function modifyComment(req, res, next) { - const commentId = Number(req.params.id); - const { content } = req.body; - const user = req.user; - const check = await prisma.comment.findUnique({ - where: { id: commentId } + const commentId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const user = req.user; + + try { + const comment = await prisma.comment.findUnique({ + where: { id: commentId }, }); - - if (user.id !== check.userId) { - return res.status(404).json({ message: 'User not matched'}) - } - try { - const updated = await prisma.comment.update({ - where: { id: commentId }, - data: { - content, - }, - }); - res.status(201).json(updated); - } catch (err) { - next(err); + if (!comment) { + return res + .status(status.NOT_FOUND) + .json({ message: "Comment not found" }); + } + if (comment.userId !== user.id) { + return res.status(status.FORBIDDEN).json({ message: "User not matched" }); } -}; -async function deleteComment(req, res) { - const commentId = Number(req.params.id); - const user = req.user; - const check = await prisma.comment.findUnique({ - where: { id: commentId } + const updated = await prisma.comment.update({ + where: { id: commentId }, + data: { + ...parsed, + }, }); - - if (user.id !== check.userId) { - return res.status(404).json({ message: 'User not matched'}) - } + res.status(status.OK).json(updated); + } catch (err) { + next(err); + } +} + +async function deleteComment(req, res) { + const commentId = Number(req.params.id); + const user = req.user; - try { - await prisma.comment.delete({ - where: { id: commentId }, - }); + try { + const comment = await prisma.comment.findUnique({ + where: { id: commentId }, + }); - res.status(204).end(); - } catch (err) { - next(err); + if (!comment) { + return res + .status(status.NOT_FOUND) + .json({ message: "Comment not found" }); + } + if (comment.userId !== user.id) { + return res.status(status.FORBIDDEN).json({ message: "User not matched" }); } -}; + await prisma.comment.delete({ + where: { id: commentId }, + }); + + res.status(status.NO_CONTENT).end(); + } catch (err) { + next(err); + } +} async function productCommentList(req, res, next) { - const productId = parseInt(req.query.id) || 1; - const lastId = req.query.lastId ? parseInt(req.query.lastId) : null; //cursor 방식의 pagination을 하기 위한 lastId 상수 지정 - try { + const parsed = querySchema.parse(req.query); // 유효성 검사 + 변환 + const { id: productId, lastId } = parsed; + + try { const comments = await prisma.comment.findMany({ - where: { //article이 아니고 product의 comment를 골라내기 위해 만든 함수 + where: { AND: [ { - articleId: null - },{ - productId - }, + articleId: null, + }, + { + productId, + }, ], }, - take: 5, //첫 불러내는 comment가 총 5개 이고 lastId가 지정이 안되면 skip 의 값은 0이 되고 있다면 1로 설정 - skip: lastId ? 1: 0, - ...(lastId && { cursor: { id: lastId } }), //lastId의 값이 있을때 괄호가 풀어지며 내부의 'cursor: { id: lastId }가 작동함 + take: 5, //첫 불러내는 comment가 총 5개 이고 lastId가 지정이 안되면 skip 의 값은 0이 되고 있다면 1로 설정 + skip: lastId ? 1 : 0, + ...(lastId && { cursor: { id: lastId } }), //lastId의 값이 있을때 괄호가 풀어지며 내부의 'cursor: { id: lastId }가 작동함 select: { - id: true, - content: true, - createdAt: true, + id: true, + content: true, + createdAt: true, }, }); - res.status(200).json(comments); + res.status(status.OK).json(comments); } catch (err) { next(err); } -}; +} async function articleCommentList(req, res, next) { - const articleId = parseInt(req.query.id) || 1; - const lastId = req.query.lastId ? parseInt(req.query.lastId) : null; - try { + const parsed = querySchema.parse(req.query); + const { id: articleId, lastId } = parsed; + + try { const comments = await prisma.comment.findMany({ - where: { //위와 반대로 product이 아니고 article의 comment를 골라내기 위해 만든 함수 + where: { AND: [ { - articleId - },{ - productId: null - }, + articleId, + }, + { + productId: null, + }, ], }, - take: 5, - skip: lastId ? 1: 0, - ...(lastId && { cursor: { id: lastId } }), + take: 5, + skip: lastId ? 1 : 0, + ...(lastId && { cursor: { id: lastId } }), select: { - id: true, - content: true, - createdAt: true, + id: true, + content: true, + createdAt: true, }, }); - res.status(201).json(comments); + + res.status(status.OK).json(comments); } catch (err) { next(err); } -}; - - router.use((err, req, res, next) => { //에러 미드웨어 설정 - if (err.code === 'P2025') { - return res.status(404).json({ error: 'Record not found' }); - } - - console.error('unhandled Error:', err); - return res.status(500).json({ error: 'Internal Server Error' }); - }); +} export default router; diff --git a/mission4/src/routers/likeRouter.js b/mission4/src/routers/likeRouter.js index 4e302099b..a3e9add4c 100644 --- a/mission4/src/routers/likeRouter.js +++ b/mission4/src/routers/likeRouter.js @@ -1,188 +1,204 @@ -import express from 'express'; -import prisma from '../lib/prisma.js'; -import passport from '../lib/passport/index.js'; +import express from "express"; +import prisma from "../lib/prisma.js"; +import passport from "../lib/passport/index.js"; +import status from "http-status"; const router = express.Router(); router.post( - '/like/articles/:id', - passport.authenticate('access-token', { session: false }), + "/like/articles/:id", + passport.authenticate("access-token", { session: false }), likeArticle ); router.post( - '/like/products/:id', - passport.authenticate('access-token', { session: false }), + "/like/products/:id", + passport.authenticate("access-token", { session: false }), likeProduct ); router.get( - '/like/articles/:id', - passport.authenticate('access-token', { session: false }), - getArticles + "/like/articles", + passport.authenticate("access-token", { session: false }), + getLikedArticles ); router.get( - '/like/products/:id', - passport.authenticate('access-token', { session: false }), - getProducts + "/like/products", + passport.authenticate("access-token", { session: false }), + getLikedProducts ); - async function likeArticle(req, res, next) { - const user = req.user; - const articleId = Number(req.params.id); - - try { - const existing = await prisma.like.findUnique({ - where: { - user_articleId: { - userId: user.id, - articleId, - }, - }, - }); - - if (existing) { - const updated = await prisma.like.update({ - where: { - userId_articleId: { - userId: user.id, - articleId, - }, - }, - data: { - like: !existing.like, - }, - }); - return res.status(200).json({ message: 'Like toggled', isliked: updated.like }); - } else { - const created = await prisma.like.create({ - data: { - like: true, - articleId, - userId: user.id, - }, - }); - return res.status(201).json({ message: 'Liked successfully', like: created.like }); - } - } catch(err) { - next(err); + const user = req.user; + const articleId = Number(req.params.id); + + try { + const article = await prisma.article.findUnique({ + where: { id: articleId }, + }); + + if (!article) { + return res + .status(status.NOT_FOUND) + .json({ message: "Article not found" }); + } + const existing = await prisma.like.findUnique({ + where: { + userId_articleId: { userId: user.id, articleId }, + }, + }); + + if (existing) { + const updated = await prisma.like.update({ + where: { + userId_articleId: { userId: user.id, articleId }, + }, + data: { + like: !existing.like, + }, + }); + return res + .status(status.OK) + .json({ message: "Like toggled", isliked: updated.like }); + } else { + const created = await prisma.like.create({ + data: { + like: true, + articleId, + userId: user.id, + }, + }); + return res + .status(status.CREATED) + .json({ message: "Liked successfully", like: created.like }); } + } catch (err) { + next(err); + } } async function likeProduct(req, res, next) { - const user = req.user; - const productId = Number(req.params.id); - - try { - const existing = await prisma.like.findUnique({ - where: { - user_productId: { - userId: user.id, - productId, - }, - }, - }); - - if (existing) { - const updated = await prisma.like.update({ - where: { - userId_productId: { - userId: user.id, - productId, - }, - }, - data: { - like: !existing.like, - }, - }); - return res.status(200).json({ message: 'Like toggled', isLiked: updated.like }); - } else { - const created = await prisma.like.create({ - data: { - like: true, - productId, - userId: user.id, - }, - }); - return res.status(201).json({ message: 'Liked successfully', isLiked: created.like }); - } - } catch(err) { - next(err); + const user = req.user; + const productId = Number(req.params.id); + + try { + const product = await prisma.product.findUnique({ + where: { id: productId }, + }); + + if (!product) { + return res + .status(status.NOT_FOUND) + .json({ message: "Product not found" }); } -} -async function getProducts(req, res, next) { - const user = req.user; - const productId = Number(req.params.id); + const existing = await prisma.like.findUnique({ + where: { + userId_productId: { userId: user.id, productId }, + }, + }); - try { - const product = await prisma.product.findUnique({ - where: { id: productId }, - select: { - id: true, - name: true, - price: true, - tags: true - } - }); - - if (!product) { - return res.status(404).json({ message: 'Product not found' }); - } - - // 좋아요 여부 확인 - const like = await prisma.like.findUnique({ + if (existing) { + const updated = await prisma.like.update({ where: { - userId_productId: { - userId: user.id, - productId, - }, + userId_productId: { userId: user.id, productId }, + }, + data: { + like: !existing.like, }, }); - - res.json({ - ...product, - isLiked: like ? like.like : false, + return res + .status(status.OK) + .json({ message: "Like toggled", isLiked: updated.like }); + } else { + const created = await prisma.like.create({ + data: { + like: true, + productId, + userId: user.id, + }, }); - } catch (err) { - next(err); + return res + .status(status.CREATED) + .json({ message: "Liked successfully", isLiked: created.like }); } + } catch (err) { + next(err); } +} + +async function getLikedArticles(req, res, next) { + const user = req.user; + + try { + const likedArticles = await prisma.like.findMany({ + where: { + userId: user.id, + articleId: { not: null }, + like: true, + }, + include: { + article: { + select: { + id: true, + title: true, + }, + }, + }, + }); - async function getArticles(req, res, next) { - const user = req.user; - const articleId = Number(req.params.id); + if (!likedArticles) { + return res + .status(status.NOT_FOUND) + .json({ message: "Articles not found" }); + } + + const articles = likedArticles.map((l) => ({ + ...l.article, + isLiked: true, + })); + + res.status(status.OK).json(articles); + } catch (err) { + next(err); + } +} - try { - const article = await prisma.article.findUnique({ - where: { id: articleId }, - select: { +async function getLikedProducts(req, res, next) { + const user = req.user; + + try { + const likedProducts = await prisma.like.findMany({ + where: { + userId: user.id, + productId: { not: null }, + like: true, + }, + include: { + product: { + select: { id: true, name: true, price: true, - tags: true - } - }); - - if (!article) { - return res.status(404).json({ message: 'Article not found' }); - } - - const like = await prisma.like.findUnique({ - where: { - userId_articleId: { - userId: user.id, - articleId, + tags: true, }, }, - }); + }, + }); - res.json({ - ...article, - isLiked: like ? like.like : false, - }); - } catch (err) { - next(err); + if (!likedProducts) { + return res + .status(status.NOT_FOUND) + .json({ message: "Product not found" }); } + + const products = likedProducts.map((l) => ({ + ...l.product, + isLiked: true, + })); + + res.status(status.OK).json(products); + } catch (err) { + next(err); } +} -export default router; \ No newline at end of file +export default router; diff --git a/mission4/src/routers/photoRouter.js b/mission4/src/routers/photoRouter.js index 9c9408ce3..99482bbe7 100644 --- a/mission4/src/routers/photoRouter.js +++ b/mission4/src/routers/photoRouter.js @@ -1,36 +1,38 @@ -import express from 'express'; -import multer from 'multer'; -import passport from '../lib/passport/index.js'; -import prisma from '../lib/prisma.js'; +import express from "express"; +import multer from "multer"; +import passport from "../lib/passport/index.js"; +import prisma from "../lib/prisma.js"; +import status from "http-status"; const router = express.Router(); -const upload = multer({ dest: 'uploads/'}) +const upload = multer({ dest: "uploads/" }); router.post( - '/users/photos', - passport.authenticate('access-token', { session: false }), - upload.single('image'), - async(req, res, next) => { - const user = req.user; + "/users/photos", + passport.authenticate("access-token", { session: false }), + upload.single("image"), + async (req, res, next) => { + const user = req.user; - if (!req.file) { - return res.status(400).json({ message: 'No file upload' }); - } + if (!req.file) { + return res.status(status.NOT_FOUND).json({ message: "No file upload" }); + } - try{ - const imageUrl = `/download/${req.file.filename}`; - const updatedUser = await prisma.user.update({ + try { + const imageUrl = `/download/${req.file.filename}`; + const updatedUser = await prisma.user.update({ where: { id: user.id }, data: { image: imageUrl }, - }); + }); - res.status(200).json({ - message: 'Photo uploaded successfully', + res.status(status.OK).json({ + message: "Photo uploaded successfully", image: updatedUser.image, - }); - } catch (err) { - next(err); + }); + } catch (err) { + next(err); + } } -}); +); -export default router; \ No newline at end of file +export default router; diff --git a/mission4/src/routers/productRouter.js b/mission4/src/routers/productRouter.js index 88b7d9132..6aab77037 100644 --- a/mission4/src/routers/productRouter.js +++ b/mission4/src/routers/productRouter.js @@ -1,188 +1,213 @@ -import express from 'express'; -import prisma from '../lib/prisma.js'; -import passport from '../lib/passport/index.js'; -import { z } from 'zod'; +import express from "express"; +import prisma from "../lib/prisma.js"; +import passport from "../lib/passport/index.js"; +import { z } from "zod"; +import status from "http-status"; const router = express.Router(); -const schema = z.object({ //유효성 검사 설정하기 - name: z.string().min(1, { message: "이름을 입력해주세요" }), - description: z.string().min(10, { message: "설명은 최소 10자 이상이어야 합니다." }).max(100, { message: "설명은 최대 100자까지 가능합니다." }), - price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }), - tags: z.string().min(1, { message: "태그는 한개 이상이여야 합니다" }), +// body 검증 (상품 생성/수정) +const productSchema = z.object({ + //유효성 검사 설정하기 + name: z.string().min(1, { message: "이름을 입력해주세요" }).optional(), + description: z + .string() + .min(10, { message: "설명은 최소 10자 이상이어야 합니다." }) + .max(100, { message: "설명은 최대 100자까지 가능합니다." }) + .optional(), + price: z.number().int() + .positive({ message: "가격은 양의 정수여야 합니다." }) + .optional(), + tags: z.string().optional().default("") +}); + +// query 검증 (상품 조회) +const productQuerySchema = z.object({ + page: z + .string() + .optional() + .default("1") + .transform(Number) + .refine((val) => val > 0, { message: "page는 1 이상의 정수여야 합니다." }), + pageSize: z + .string() + .optional() + .default("5") + .transform(Number) + .refine((val) => val > 0 && val <= 100, { + message: "pageSize는 1~100 사이여야 합니다.", + }), + keyword: z.string().optional().default(""), }); router.post( - '/products', - passport.authenticate('access-token', { session: false }), + "/products", + passport.authenticate("access-token", { session: false }), createProduct ); -router.get('/products', getProducts); +router.get("/products", getProducts); router.patch( - '/products/:id', - passport.authenticate('access-token', { session: false }), + "/products/:id", + passport.authenticate("access-token", { session: false }), modifyProduct ); -router.delete('/products/:id', - passport.authenticate('local', { session: false }), - deleteProduct +router.delete( + "/products/:id", + passport.authenticate("access-token", { session: false }), + deleteProduct ); -router.get('/products/:id', - passport.authenticate('access-token', { session: false }), - getDetailProduct +router.get( + "/products/:id", + passport.authenticate("access-token", { session: false }), + getDetailProduct ); async function createProduct(req, res, next) { -try { - const validatedData = schema.parse(req.body); - const user = req.user; - const product = await prisma.product.create ({ - data: { - name: validatedData.name, - description: validatedData.description, - price: validatedData.price, - tags: validatedData.tags, - userId: user.id - }, - }); - - return res.status(201).json(product); - } catch (err) { - next(err); - } + const parsed = productSchema.parse(req.body); + const user = req.user; + + try { + const product = await prisma.product.create({ + data: { + ...parsed, + userId: user.id, + }, + }); + + res.status(status.CREATED).json(product); + } catch (err) { + next(err); + } } async function getProducts(req, res, next) { -try { - const page = parseInt(req.query.page) || 1; //값이 없을 경우도 수식하기 위함 - const keyword = req.query.keyword ? decodeURIComponent(req.query.keyword) : ''; - const where = keyword //name과 description에서 원하는 keyword가 들어간 데이터를 찾도록 만든 변수 - ? { - OR: [ - { - name: { - contains: keyword, - mode: 'insensitive', //대소문자 구분 없이 검색하기 위해 - }, + const { page, pageSize, keyword } = productQuerySchema.parse(req.query); + const where = keyword //name과 description에서 원하는 keyword가 들어간 데이터를 찾도록 만든 변수 + ? { + OR: [ + { + name: { + contains: keyword, + mode: "insensitive", //대소문자 구분 없이 검색하기 위해 }, - { - description: { - contains: keyword, - mode: 'insensitive', - }, + }, + { + description: { + contains: keyword, + mode: "insensitive", }, - ], - } - : {}; //기본값 {}으로 빈 객체를 수식하기 위함 - - const products = await prisma.product.findMany({ - skip: (page - 1) * 5, - take: 5, - orderBy: { // 최신 순서대로 정렬하기(최신순) - createdAt: 'desc', - }, - select: { - id: true, - name: true, - description: true, - price: true, - tags: true, - createdAt: true, - }, - where, - }); - - res.status(200).json(products); - } catch (err) { - next(err); - } + }, + ], + } + : {}; //기본값 {}으로 빈 객체를 수식하기 위함 + + try { + const products = await prisma.product.findMany({ + skip: (page - 1) * pageSize, + take: pageSize, + orderBy: { + // 최신 순서대로 정렬하기(최신순) + createdAt: "desc", + }, + select: { + id: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + where, + }); + + res.status(status.OK).json(products); + } catch (err) { + next(err); + } } async function modifyProduct(req, res, next) { - const productId = Number(req.params.id); - const validatedData = schema.parse(req.body); - const user = req.user; - const check = await prisma.product.findUnique({ - where: { id: productId } + const productId = Number(req.params.id); + const parsed = productSchema.parse(req.body); + const user = req.user; + + try { + const product = await prisma.product.findUnique({ + where: { id: productId }, }); - - if (user.Id !== check.userId) { - return res.status(404).json({ message: 'User not matched'}) - } - try{ - const updated = await prisma.product.update({ - where: { id: productId }, - data: { - name: validatedData.name, - description: validatedData.description, - price: validatedData.price, - tags: validatedData.tags, - }, - }); - res.status(201).json(updated); - } catch (err) { - next(err); + if (!product) { + return res + .status(status.NOT_FOUND) + .json({ message: "Product not found" }); } + if (product.userId !== user.id) { + return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + } + + const updated = await prisma.product.update({ + where: { id: productId }, + data: { + ...parsed, + }, + }); + res.status(status.OK).json(updated); + } catch (err) { + next(err); + } } async function deleteProduct(req, res, next) { - const productId = Number(req.params.id); - const user = req.user; - const check = await prisma.product.findUnique({ - where: { id: productId } + const productId = Number(req.params.id); + const user = req.user; + + try { + const product = await prisma.product.findUnique({ + where: { id: productId }, }); - - if (user.Id !== check.userId) { - return res.status(404).json({ message: 'User not matched'}) - } - try { - await prisma.product.delete({ - where: { id: productId }, - }); - res.status(204).end(); - } catch (err) { - next(err); + if (!product) { + return res + .status(status.NOT_FOUND) + .json({ message: "Product not found" }); } + if (product.userId !== user.id) { + return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + } + + await prisma.product.delete({ + where: { id: productId }, + }); + res.status(status.NO_CONTENT).end(); + } catch (err) { + next(err); + } } async function getDetailProduct(req, res, next) { - const productId = Number(req.params.id); - - try { - const product = await prisma.product.findUnique({ - where: { id: productId }, - select: { - id: true, - name: true, - description: true, - price: true, - tags: true, - createdAt: true, - }, - }); + const productId = Number(req.params.id); + + try { + const product = await prisma.product.findUnique({ + where: { id: productId }, + select: { + id: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + }); + if (!product) { - return res.status(404).json({ error: 'Product not found'}); - } - res.status(200).json(product); - } catch (err) { - next(err); + return res.status(status.NOT_FOUND).json({ error: "Product not found" }); } -} - router.use((err, req, res, next) => { //에러 미드웨어 설정 - if (err instanceof z.ZodError) { - return res.status(400).json({ error: err.errors }); - } - - if (err.code === 'P2025') { - return res.status(404).json({ error: 'Record not found' }); - } - - console.error('unhandled Error:', err); - return res.status(500).json({ error: 'Internal Server Error' }); - }); - + res.status(status.OK).json(product); + } catch (err) { + next(err); + } +} export default router; diff --git a/mission4/src/routers/userRouter.js b/mission4/src/routers/userRouter.js index ea7b101d4..356ea22dc 100644 --- a/mission4/src/routers/userRouter.js +++ b/mission4/src/routers/userRouter.js @@ -1,114 +1,125 @@ -import express from 'express'; -import bcrypt from 'bcrypt'; -import prisma from '../lib/prisma.js'; -import passport from '../lib/passport/index.js'; -import { generateTokens } from '../lib/token.js'; +import express from "express"; +import bcrypt from "bcrypt"; +import prisma from "../lib/prisma.js"; +import passport from "../lib/passport/index.js"; +import status from "http-status"; +import { generateTokens } from "../lib/token.js"; import { NODE_ENV, ACCESS_TOKEN_COOKIE_NAME, REFRESH_TOKEN_COOKIE_NAME, -} from '../lib/constants.js'; +} from "../lib/constants.js"; const router = express.Router(); -router.post('/users/register', register); -router.post('/users/login', - passport.authenticate('local', { session: false }), - login +router.post("/users/register", register); +router.post( + "/users/login", + passport.authenticate("local", { session: false }), + login ); -router.get('/users/profile', - passport.authenticate('access-token', { session: false }), - profile +router.get( + "/users/profile", + passport.authenticate("access-token", { session: false }), + profile ); router.patch( - '/users/modifyInformation', - passport.authenticate('access-token', { session: false }), + "/users/modifyInformation", + passport.authenticate("access-token", { session: false }), modifyinformation ); router.patch( - '/users/modifyPassword', - passport.authenticate('access-token', { session: false }), + "/users/modifyPassword", + passport.authenticate("access-token", { session: false }), modifyPassword ); router.get( - '/users/products', - passport.authenticate('access-token', { session: false }), + "/users/products", + passport.authenticate("access-token", { session: false }), products ); router.post( - '/users/refresh', - passport.authenticate('refresh-token', { session: false }), + "/users/refresh", + passport.authenticate("refresh-token", { session: false }), refreshTokens ); -router.post('/users/logout', logout); +router.post("/users/logout", logout); async function register(req, res, next) { - const { email, nickname, password } = req.body; - - try{ + const { email, nickname, password } = req.body; + + try { const check = await prisma.user.findUnique({ where: { email } }); if (check) { - return res.status(409).json({ message: 'This ID already exists' }); + return res + .status(status.CONFLICT) + .json({ message: "This ID already exists" }); } const salt = await bcrypt.genSalt(10); const hashedPassword = await bcrypt.hash(password, salt); const user = await prisma.user.create({ - data: { email, nickname, password: hashedPassword }, + data: { email, nickname, password: hashedPassword }, }); - res.status(201).json({ "message": "User registered successfully" }); -} catch(err) { + res + .status(status.CREATED) + .json({ message: "User registered successfully" }); + } catch (err) { next(err); -} + } } function login(req, res, next) { - if(!req.user) { - return res.status(401).json({ message: 'Unauthorized' }) - } - - try{ + if (!req.user) { + return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + } + + try { const { accessToken, refreshToken } = generateTokens(req.user.id); setTokenCookies(res, accessToken, refreshToken); - res.status(200).json({ "token": accessToken }); - } catch(err) { - next(err); - } + res.status(status.OK).json({ token: accessToken, refreshToken }); + } catch (err) { + next(err); + } } async function profile(req, res, next) { const user = req.user; + try { const profile = await prisma.user.findUnique({ where: { - id: user.id + id: user.id, }, select: { id: true, email: true, nickname: true, image: true, - createdAt: true - } + createdAt: true, + updatedAt: true, + }, }); - res.status(200).json(profile); - } catch(err) { + res.status(status.OK).json(profile); + } catch (err) { next(err); } -}; +} async function modifyinformation(req, res, next) { const user = req.user; const { nickname, image } = req.body; - try{ + try { const updateData = {}; if (nickname) updateData.nickname = nickname; if (image) updateData.image = image; if (Object.keys(updateData).length === 0) { - return res.status(400).json({ message: 'No update data provided' }) + return res + .status(status.BAD_REQUEST) + .json({ message: "No update data provided" }); } const updatedUser = await prisma.user.update({ @@ -120,15 +131,14 @@ async function modifyinformation(req, res, next) { nickname: true, image: true, createdAt: true, - updateAt: true, }, }); - res.status(200).json({ - message: 'User information updated successfully', + res.status(status.OK).json({ + message: "User information updated successfully", user: updatedUser, - }) - } catch(err) { + }); + } catch (err) { next(err); } } @@ -136,46 +146,53 @@ async function modifyinformation(req, res, next) { async function modifyPassword(req, res, next) { const user = req.user; const { password } = req.body; - - try{ + + try { const salt = await bcrypt.genSalt(10); const hashedPassword = await bcrypt.hash(password, salt); await prisma.user.update({ where: { id: user.id }, data: { - password: hashedPassword + password: hashedPassword, }, }); - res.status(200).json({ message: 'User passowrd updated successfully'}); - } catch(err){ + res + .status(status.OK) + .json({ message: "User passowrd updated successfully" }); + } catch (err) { next(err); } } -async function products(req, res, nest) { +async function products(req, res, next) { const user = req.user; - const products = await prisma.product.findMany({ - where: { - userId: user.id - }, - select: { - name: true, - description: true, - price: true, - tags: true - }, - }); - if (!products) { - return res.status(400).json({ message: "No product" }); + + try { + const products = await prisma.product.findMany({ + where: { + userId: user.id, + }, + select: { + name: true, + description: true, + price: true, + tags: true, + }, + }); + if (!products) { + return res.status(status.NOT_FOUND).json({ message: "No product" }); + } + res.status(status.OK).json(products); + } catch (err) { + next(err); } - res.status(200).json(products); } function logout(req, res) { clearTokenCookies(res); - res.status(200).send({ message: 'Logged out successfully' }); + res.status(status.OK).send({ message: "Logged out successfully" }); } async function refreshTokens(req, res) { @@ -184,20 +201,20 @@ async function refreshTokens(req, res) { user.id ); setTokenCookies(res, accessToken, newRefreshToken); - res.status(200).send({ message: 'Tokens refreshed' }); + res.status(status.OK).send({ message: "Tokens refreshed" }); } function setTokenCookies(res, accessToken, refreshToken) { res.cookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, { httpOnly: true, - secure: NODE_ENV === 'production', + secure: NODE_ENV === "production", maxAge: 1 * 60 * 60 * 1000, // 1 hour }); res.cookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken, { httpOnly: true, - secure: NODE_ENV === 'production', + secure: NODE_ENV === "production", maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days - path: '/users/refresh', + path: "/users/refresh", }); } From 57109c7926e5b82a944b7edcc6ace3bc69a8b1cc Mon Sep 17 00:00:00 2001 From: Batur-s Date: Fri, 5 Sep 2025 16:34:28 +0900 Subject: [PATCH 24/38] =?UTF-8?q?Fix:=20lastId=EB=A5=BC=20optional?= =?UTF-8?q?=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 --- mission4/src/routers/commentRouter.js | 44 ++++++++++++++------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/mission4/src/routers/commentRouter.js b/mission4/src/routers/commentRouter.js index 071752946..b42bea958 100644 --- a/mission4/src/routers/commentRouter.js +++ b/mission4/src/routers/commentRouter.js @@ -14,16 +14,12 @@ const commentSchema = z.object({ .max(100, { message: "덧글은 최대 100자까지 가능합니다." }), }); -const commentQuerySchema = z.object({ - id: z - .string() - .regex(/^\d+$/, { message: "id는 숫자여야 합니다." }) - .transform(Number), - lastId: z - .string() - .regex(/^\d+$/, { message: "lastId는 숫자여야 합니다." }) - .transform(Number) - .optional(), +const commentListSchema = z.object({ + id: z.coerce + .number() + .int() + .positive({ message: "id는 양의 정수여야 합니다." }), + lastId: z.coerce.number().int().positive().optional(), }); router.post( @@ -47,12 +43,12 @@ router.delete( deleteComment ); router.get( - "/comments/products", + "/comments/products/:id", passport.authenticate("access-token", { session: false }), productCommentList ); router.get( - "/comments/articles", + "/comments/articles/:id", passport.authenticate("access-token", { session: false }), articleCommentList ); @@ -130,7 +126,7 @@ async function modifyComment(req, res, next) { } } -async function deleteComment(req, res) { +async function deleteComment(req, res, next) { const commentId = Number(req.params.id); const user = req.user; @@ -158,10 +154,13 @@ async function deleteComment(req, res) { } async function productCommentList(req, res, next) { - const parsed = querySchema.parse(req.query); // 유효성 검사 + 변환 - const { id: productId, lastId } = parsed; - try { + const parsed = commentListSchema.parse({ + id: req.params.id, + lastId: req.query.lastId, + }); + const { id: productId, lastId } = parsed; + const comments = await prisma.comment.findMany({ where: { AND: [ @@ -173,9 +172,9 @@ async function productCommentList(req, res, next) { }, ], }, - take: 5, //첫 불러내는 comment가 총 5개 이고 lastId가 지정이 안되면 skip 의 값은 0이 되고 있다면 1로 설정 + take: 5, skip: lastId ? 1 : 0, - ...(lastId && { cursor: { id: lastId } }), //lastId의 값이 있을때 괄호가 풀어지며 내부의 'cursor: { id: lastId }가 작동함 + ...(lastId && { cursor: { id: lastId } }), select: { id: true, content: true, @@ -190,10 +189,13 @@ async function productCommentList(req, res, next) { } async function articleCommentList(req, res, next) { - const parsed = querySchema.parse(req.query); - const { id: articleId, lastId } = parsed; - try { + const parsed = commentListSchema.parse({ + id: req.params.id, + lastId: req.query.lastId, + }); + const { id: articleId, lastId } = parsed; + const comments = await prisma.comment.findMany({ where: { AND: [ From 42b618f719d25ea828a851ba9d1b29e44051fca5 Mon Sep 17 00:00:00 2001 From: Batur-s Date: Mon, 15 Sep 2025 13:14:37 +0900 Subject: [PATCH 25/38] Feat: Refactoring and dtos --- mission5/.gitignore | 5 + mission5/package-lock.json | 3128 +++++++++++++++++ mission5/package.json | 49 + .../20250904083711_test/migration.sql | 94 + .../prisma/migrations/migration_lock.toml | 3 + mission5/prisma/schema.prisma | 75 + mission5/src/app.ts | 31 + mission5/src/lib/constants.ts | 21 + mission5/src/lib/passport/index.ts | 9 + mission5/src/lib/passport/jwtStrategy.ts | 45 + mission5/src/lib/passport/localStrategy.ts | 27 + mission5/src/lib/prisma.ts | 5 + mission5/src/lib/token.ts | 27 + mission5/src/middlewares/errorHandler.ts | 22 + mission5/src/routers/articleRouter.ts | 203 ++ mission5/src/routers/commentRouter.ts | 230 ++ mission5/src/routers/index.ts | 18 + mission5/src/routers/likeRouter.ts | 208 ++ mission5/src/routers/photoRouter.ts | 39 + mission5/src/routers/productRouter.ts | 220 ++ mission5/src/routers/userRouter.ts | 227 ++ mission5/src/types/express.d.ts | 11 + mission5/tsconfig.json | 48 + mission5_dtos/.gitignore | 5 + mission5_dtos/package-lock.json | 3128 +++++++++++++++++ mission5_dtos/package.json | 49 + .../20250904083711_test/migration.sql | 94 + .../prisma/migrations/migration_lock.toml | 3 + mission5_dtos/prisma/schema.prisma | 75 + mission5_dtos/src/app.ts | 31 + .../src/controllers/articleController.ts | 102 + .../src/controllers/commentController.ts | 90 + .../src/controllers/likeController.ts | 51 + .../src/controllers/photoController.ts | 31 + .../src/controllers/productController.ts | 90 + .../src/controllers/userController.ts | 89 + mission5_dtos/src/lib/constants.ts | 21 + mission5_dtos/src/lib/cookieUtil.ts | 22 + mission5_dtos/src/lib/passport/index.ts | 9 + mission5_dtos/src/lib/passport/jwtStrategy.ts | 45 + .../src/lib/passport/localStrategy.ts | 27 + mission5_dtos/src/lib/prisma.ts | 5 + mission5_dtos/src/lib/token.ts | 27 + mission5_dtos/src/middlewares/errorHandler.ts | 22 + .../src/repositories/articleRepository.ts | 44 + .../src/repositories/commentRepository.ts | 50 + .../src/repositories/likeRepository.ts | 67 + .../src/repositories/productRepository.ts | 48 + .../src/repositories/userRepository.ts | 29 + mission5_dtos/src/routers/articleRouter.ts | 14 + mission5_dtos/src/routers/commentRouter.ts | 15 + mission5_dtos/src/routers/index.ts | 19 + mission5_dtos/src/routers/likeRouter.ts | 13 + mission5_dtos/src/routers/photoRouter.ts | 18 + mission5_dtos/src/routers/productRouter.ts | 14 + mission5_dtos/src/routers/userRouter.ts | 17 + mission5_dtos/src/services/articleService.ts | 46 + mission5_dtos/src/services/commentService.ts | 35 + mission5_dtos/src/services/likeService.ts | 35 + mission5_dtos/src/services/productService.ts | 42 + mission5_dtos/src/services/userService.ts | 47 + mission5_dtos/src/types/express.d.ts | 11 + mission5_dtos/tsconfig.json | 48 + 63 files changed, 9373 insertions(+) create mode 100644 mission5/.gitignore create mode 100644 mission5/package-lock.json create mode 100644 mission5/package.json create mode 100644 mission5/prisma/migrations/20250904083711_test/migration.sql create mode 100644 mission5/prisma/migrations/migration_lock.toml create mode 100644 mission5/prisma/schema.prisma create mode 100644 mission5/src/app.ts create mode 100644 mission5/src/lib/constants.ts create mode 100644 mission5/src/lib/passport/index.ts create mode 100644 mission5/src/lib/passport/jwtStrategy.ts create mode 100644 mission5/src/lib/passport/localStrategy.ts create mode 100644 mission5/src/lib/prisma.ts create mode 100644 mission5/src/lib/token.ts create mode 100644 mission5/src/middlewares/errorHandler.ts create mode 100644 mission5/src/routers/articleRouter.ts create mode 100644 mission5/src/routers/commentRouter.ts create mode 100644 mission5/src/routers/index.ts create mode 100644 mission5/src/routers/likeRouter.ts create mode 100644 mission5/src/routers/photoRouter.ts create mode 100644 mission5/src/routers/productRouter.ts create mode 100644 mission5/src/routers/userRouter.ts create mode 100644 mission5/src/types/express.d.ts create mode 100644 mission5/tsconfig.json create mode 100644 mission5_dtos/.gitignore create mode 100644 mission5_dtos/package-lock.json create mode 100644 mission5_dtos/package.json create mode 100644 mission5_dtos/prisma/migrations/20250904083711_test/migration.sql create mode 100644 mission5_dtos/prisma/migrations/migration_lock.toml create mode 100644 mission5_dtos/prisma/schema.prisma create mode 100644 mission5_dtos/src/app.ts create mode 100644 mission5_dtos/src/controllers/articleController.ts create mode 100644 mission5_dtos/src/controllers/commentController.ts create mode 100644 mission5_dtos/src/controllers/likeController.ts create mode 100644 mission5_dtos/src/controllers/photoController.ts create mode 100644 mission5_dtos/src/controllers/productController.ts create mode 100644 mission5_dtos/src/controllers/userController.ts create mode 100644 mission5_dtos/src/lib/constants.ts create mode 100644 mission5_dtos/src/lib/cookieUtil.ts create mode 100644 mission5_dtos/src/lib/passport/index.ts create mode 100644 mission5_dtos/src/lib/passport/jwtStrategy.ts create mode 100644 mission5_dtos/src/lib/passport/localStrategy.ts create mode 100644 mission5_dtos/src/lib/prisma.ts create mode 100644 mission5_dtos/src/lib/token.ts create mode 100644 mission5_dtos/src/middlewares/errorHandler.ts create mode 100644 mission5_dtos/src/repositories/articleRepository.ts create mode 100644 mission5_dtos/src/repositories/commentRepository.ts create mode 100644 mission5_dtos/src/repositories/likeRepository.ts create mode 100644 mission5_dtos/src/repositories/productRepository.ts create mode 100644 mission5_dtos/src/repositories/userRepository.ts create mode 100644 mission5_dtos/src/routers/articleRouter.ts create mode 100644 mission5_dtos/src/routers/commentRouter.ts create mode 100644 mission5_dtos/src/routers/index.ts create mode 100644 mission5_dtos/src/routers/likeRouter.ts create mode 100644 mission5_dtos/src/routers/photoRouter.ts create mode 100644 mission5_dtos/src/routers/productRouter.ts create mode 100644 mission5_dtos/src/routers/userRouter.ts create mode 100644 mission5_dtos/src/services/articleService.ts create mode 100644 mission5_dtos/src/services/commentService.ts create mode 100644 mission5_dtos/src/services/likeService.ts create mode 100644 mission5_dtos/src/services/productService.ts create mode 100644 mission5_dtos/src/services/userService.ts create mode 100644 mission5_dtos/src/types/express.d.ts create mode 100644 mission5_dtos/tsconfig.json diff --git a/mission5/.gitignore b/mission5/.gitignore new file mode 100644 index 000000000..9f62ec0b8 --- /dev/null +++ b/mission5/.gitignore @@ -0,0 +1,5 @@ +node_modules +# Keep environment variables out of version control +.env + +/generated/prisma diff --git a/mission5/package-lock.json b/mission5/package-lock.json new file mode 100644 index 000000000..4b76c5e8d --- /dev/null +++ b/mission5/package-lock.json @@ -0,0 +1,3128 @@ +{ + "name": "mission3", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mission3", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@prisma/client": "^6.13.0", + "bcrypt": "^6.0.0", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^17.2.2", + "express": "^5.1.0", + "http-status": "^2.1.0", + "multer": "^2.0.2", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", + "passport-local": "^1.0.0", + "tsx": "^4.20.5", + "zod": "^4.0.14" + }, + "devDependencies": { + "@types/bcrypt": "^6.0.0", + "@types/cookie-parser": "^1.4.9", + "@types/cors": "^2.8.19", + "@types/express": "^5.0.3", + "@types/jsonwebtoken": "^9.0.10", + "@types/multer": "^2.0.0", + "@types/node": "^24.3.1", + "@types/passport": "^1.0.17", + "@types/passport-jwt": "^4.0.1", + "@types/passport-local": "^1.0.38", + "prisma": "^6.15.0", + "ts-node": "^10.9.2", + "ts-node-dev": "^2.0.0", + "typescript": "^5.9.2" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@prisma/client": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.13.0.tgz", + "integrity": "sha512-8m2+I3dQovkV8CkDMluiwEV1TxV9EXdT6xaCz39O6jYw7mkf5gwfmi+cL4LJsEPwz5tG7sreBwkRpEMJedGYUQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "prisma": "*", + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@prisma/config": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.15.0.tgz", + "integrity": "sha512-KMEoec9b2u6zX0EbSEx/dRpx1oNLjqJEBZYyK0S3TTIbZ7GEGoVyGyFRk4C72+A38cuPLbfQGQvgOD+gBErKlA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "c12": "3.1.0", + "deepmerge-ts": "7.1.5", + "effect": "3.16.12", + "empathic": "2.0.0" + } + }, + "node_modules/@prisma/debug": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.15.0.tgz", + "integrity": "sha512-y7cSeLuQmyt+A3hstAs6tsuAiVXSnw9T55ra77z0nbNkA8Lcq9rNcQg6PI00by/+WnE/aMRJ/W7sZWn2cgIy1g==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.15.0.tgz", + "integrity": "sha512-opITiR5ddFJ1N2iqa7mkRlohCZqVSsHhRcc29QXeldMljOf4FSellLT0J5goVb64EzRTKcIDeIsJBgmilNcKxA==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/fetch-engine": "6.15.0", + "@prisma/get-platform": "6.15.0" + } + }, + "node_modules/@prisma/engines-version": { + "version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb.tgz", + "integrity": "sha512-a/46aK5j6L3ePwilZYEgYDPrhBQ/n4gYjLxT5YncUTJJNRnTCVjPF86QdzUOLRdYjCLfhtZp9aum90W0J+trrg==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.15.0.tgz", + "integrity": "sha512-xcT5f6b+OWBq6vTUnRCc7qL+Im570CtwvgSj+0MTSGA1o9UDSKZ/WANvwtiRXdbYWECpyC3CukoG3A04VTAPHw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/get-platform": "6.15.0" + } + }, + "node_modules/@prisma/get-platform": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.15.0.tgz", + "integrity": "sha512-Jbb+Xbxyp05NSR1x2epabetHiXvpO8tdN2YNoWoA/ZsbYyxxu/CO/ROBauIFuMXs3Ti+W7N7SJtWsHGaWte9Rg==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-/oJGukuH3D2+D+3H4JWLaAsJ/ji86dhRidzZ/Od7H/i8g+aCmvkeCc6Ni/f9uxGLSQVCRZkX2/lqEFG2BvWtlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie-parser": { + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.9.tgz", + "integrity": "sha512-tGZiZ2Gtc4m3wIdLkZ8mkj1T6CEHb35+VApbL2T14Dew8HA7c+04dmKqsKRNC+8RJPm16JEK0tFSwdZqubfc4g==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz", + "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", + "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/multer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz", + "integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/node": { + "version": "24.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz", + "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.10.0" + } + }, + "node_modules/@types/passport": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", + "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/passport-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-Y0Ykz6nWP4jpxgEUYq8NoVZeCQPo1ZndJLfapI249g1jHChvRfZRO/LS3tqu26YgAS/laI1qx98sYGz0IalRXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/jsonwebtoken": "*", + "@types/passport-strategy": "*" + } + }, + "node_modules/@types/passport-local": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.38.tgz", + "integrity": "sha512-nsrW4A963lYE7lNTv9cr5WmiUD1ibYJvWrpE13oxApFsRt77b0RdtZvKbCdNIY4v/QZ6TRQWaDDEwV1kCTmcXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-strategy": "*" + } + }, + "node_modules/@types/passport-strategy": { + "version": "0.2.38", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", + "integrity": "sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", + "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.8", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", + "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/strip-json-comments": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", + "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "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==", + "license": "MIT" + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.0", + "node-gyp-build": "^4.8.4" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "BSD-3-Clause" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/c12": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", + "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.3", + "confbox": "^0.2.2", + "defu": "^6.1.4", + "dotenv": "^16.6.1", + "exsolve": "^1.0.7", + "giget": "^2.0.0", + "jiti": "^2.4.2", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^1.0.0", + "pkg-types": "^2.2.0", + "rc9": "^2.1.2" + }, + "peerDependencies": { + "magicast": "^0.3.5" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } + } + }, + "node_modules/c12/node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "devOptional": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "consola": "^3.2.3" + } + }, + "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, + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "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, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deepmerge-ts": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", + "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dotenv": { + "version": "17.2.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", + "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/dynamic-dedupe": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", + "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + } + }, + "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==", + "license": "Apache-2.0", + "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", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/effect": { + "version": "3.16.12", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.16.12.tgz", + "integrity": "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "fast-check": "^3.23.1" + } + }, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/fast-check": { + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", + "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "dependencies": { + "pure-rand": "^6.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/giget": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", + "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.0", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.6", + "nypm": "^0.6.0", + "pathe": "^2.0.3" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "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/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, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-status": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-status/-/http-status-2.1.0.tgz", + "integrity": "sha512-O5kPr7AW7wYd/BBiOezTwnVAnmSNFY+J7hlZD2X5IOxVBetjcHAiTXhzj0gMrnojQlwy+UT1/Y3H3vJ3UlmvLA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 0.4.0" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "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==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/jiti": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", + "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "devOptional": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", + "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.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "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, + "license": "ISC" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.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, + "license": "ISC", + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/multer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", + "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", + "object-assign": "^4.1.1", + "type-is": "^1.6.18", + "xtend": "^4.0.2" + }, + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/multer/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-addon-api": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz", + "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nypm": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.1.tgz", + "integrity": "sha512-hlacBiRiv1k9hZFiphPUkfSQ/ZfQzZDzC+8z0wL3lvDAOUu/2NnChkKuMoMjNur/9OpKuz2QsIeiPVN0xM5Q0w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.2", + "pathe": "^2.0.3", + "pkg-types": "^2.2.0", + "tinyexec": "^1.0.1" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "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==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "license": "MIT", + "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-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", + "license": "MIT", + "dependencies": { + "jsonwebtoken": "^9.0.0", + "passport-strategy": "^1.0.0" + } + }, + "node_modules/passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "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-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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, + "node_modules/prisma": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.15.0.tgz", + "integrity": "sha512-E6RCgOt+kUVtjtZgLQDBJ6md2tDItLJNExwI0XJeBc1FKL+Vwb+ovxXxuok9r8oBgsOXBA33fGDuE/0qDdCWqQ==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/config": "6.15.0", + "@prisma/engines": "6.15.0" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc9": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", + "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "defu": "^6.1.4", + "destr": "^2.0.3" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "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" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tinyexec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", + "devOptional": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "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/ts-node-dev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz", + "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.1", + "dynamic-dedupe": "^0.3.0", + "minimist": "^1.2.6", + "mkdirp": "^1.0.4", + "resolve": "^1.0.0", + "rimraf": "^2.6.1", + "source-map-support": "^0.5.12", + "tree-kill": "^1.2.2", + "ts-node": "^10.4.0", + "tsconfig": "^7.0.0" + }, + "bin": { + "ts-node-dev": "lib/bin.js", + "tsnd": "lib/bin.js" + }, + "engines": { + "node": ">=0.8.0" + }, + "peerDependencies": { + "node-notifier": "*", + "typescript": "*" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/ts-node-dev/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "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" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/ts-node-dev/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-node-dev/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/tsconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", + "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/strip-bom": "^3.0.0", + "@types/strip-json-comments": "0.0.30", + "strip-bom": "^3.0.0", + "strip-json-comments": "^2.0.0" + } + }, + "node_modules/tsx": { + "version": "4.20.5", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.5.tgz", + "integrity": "sha512-+wKjMNU9w/EaQayHXb7WA7ZaHY6hN8WgfvHNQ3t1PnU91/7O8TcTnIhCDYTZwnt8JsO9IBqZ30Ln1r7pPF52Aw==", + "license": "MIT", + "dependencies": { + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "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==", + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/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, + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/zod": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.0.14.tgz", + "integrity": "sha512-nGFJTnJN6cM2v9kXL+SOBq3AtjQby3Mv5ySGFof5UGRHrRioSJ5iG680cYNjE/yWk671nROcpPj4hAS8nyLhSw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/mission5/package.json b/mission5/package.json new file mode 100644 index 000000000..a68267d04 --- /dev/null +++ b/mission5/package.json @@ -0,0 +1,49 @@ +{ + "name": "mission3", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "dev": "ts-node --files src/app.ts", + "start": "node dist/app.js", + "lint": "eslint . --ext .ts", + "prisma:generate": "prisma generate", + "prisma:migrate": "prisma migrate dev" + }, + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "@prisma/client": "^6.13.0", + "bcrypt": "^6.0.0", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^17.2.2", + "express": "^5.1.0", + "http-status": "^2.1.0", + "multer": "^2.0.2", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", + "passport-local": "^1.0.0", + "tsx": "^4.20.5", + "zod": "^4.0.14" + }, + "devDependencies": { + "@types/bcrypt": "^6.0.0", + "@types/cookie-parser": "^1.4.9", + "@types/cors": "^2.8.19", + "@types/express": "^5.0.3", + "@types/jsonwebtoken": "^9.0.10", + "@types/multer": "^2.0.0", + "@types/node": "^24.3.1", + "@types/passport": "^1.0.17", + "@types/passport-jwt": "^4.0.1", + "@types/passport-local": "^1.0.38", + "prisma": "^6.15.0", + "ts-node": "^10.9.2", + "ts-node-dev": "^2.0.0", + "typescript": "^5.9.2" + }, + "prisma": { + "seed": "node prisma/seed.js" + } +} diff --git a/mission5/prisma/migrations/20250904083711_test/migration.sql b/mission5/prisma/migrations/20250904083711_test/migration.sql new file mode 100644 index 000000000..ad7fbdc5d --- /dev/null +++ b/mission5/prisma/migrations/20250904083711_test/migration.sql @@ -0,0 +1,94 @@ +-- CreateTable +CREATE TABLE "public"."User" ( + "id" SERIAL NOT NULL, + "email" TEXT NOT NULL, + "nickname" TEXT NOT NULL, + "image" TEXT, + "password" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Product" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT NOT NULL, + "price" INTEGER NOT NULL, + "tags" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Product_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Article" ( + "id" SERIAL NOT NULL, + "title" TEXT NOT NULL, + "content" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Article_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Comment" ( + "id" SERIAL NOT NULL, + "content" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "productId" INTEGER, + "articleId" INTEGER, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Comment_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Like" ( + "id" SERIAL NOT NULL, + "like" BOOLEAN NOT NULL DEFAULT true, + "userId" INTEGER NOT NULL, + "productId" INTEGER, + "articleId" INTEGER, + + CONSTRAINT "Like_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "public"."User"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "Like_userId_productId_key" ON "public"."Like"("userId", "productId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Like_userId_articleId_key" ON "public"."Like"("userId", "articleId"); + +-- AddForeignKey +ALTER TABLE "public"."Product" ADD CONSTRAINT "Product_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Article" ADD CONSTRAINT "Article_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_productId_fkey" FOREIGN KEY ("productId") REFERENCES "public"."Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "public"."Article"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_productId_fkey" FOREIGN KEY ("productId") REFERENCES "public"."Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "public"."Article"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/mission5/prisma/migrations/migration_lock.toml b/mission5/prisma/migrations/migration_lock.toml new file mode 100644 index 000000000..044d57cdb --- /dev/null +++ b/mission5/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (e.g., Git) +provider = "postgresql" diff --git a/mission5/prisma/schema.prisma b/mission5/prisma/schema.prisma new file mode 100644 index 000000000..05365cc8e --- /dev/null +++ b/mission5/prisma/schema.prisma @@ -0,0 +1,75 @@ +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" +} + +model User { + id Int @id @default(autoincrement()) + email String @unique + nickname String + image String? + password String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + article Article[] + product Product[] + comment Comment[] + like Like[] +} + +model Product { + id Int @id @default(autoincrement()) + name String + description String + price Int + tags String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + comment Comment[] + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + like Like[] +} + +model Article { + id Int @id @default(autoincrement()) + title String + content String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + comment Comment[] + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + like Like[] +} + +model Comment { + id Int @id @default(autoincrement()) + content String + createdAt DateTime @default(now()) + productId Int? + product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) + articleId Int? + article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) +} + +model Like { + id Int @id @default(autoincrement()) + like Boolean @default(true) + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + productId Int? + product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) + articleId Int? + article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) + + // 유저-상품, 유저-게시글 각각 중복 방지, 좋아요 중첩 방지 + @@unique([userId, productId]) + @@unique([userId, articleId]) +} \ No newline at end of file diff --git a/mission5/src/app.ts b/mission5/src/app.ts new file mode 100644 index 000000000..2cedd491e --- /dev/null +++ b/mission5/src/app.ts @@ -0,0 +1,31 @@ +import express from "express"; +import cookieParser from "cookie-parser"; +import router from "./routers/index"; +import { PORT } from "./lib/constants"; +import passport from "./lib/passport/index"; +import cors from "cors"; +import { errorHandler } from "./middlewares/errorHandler"; + +const app = express(); + +app.use(express.urlencoded({ extended: true })); + +app.use(cookieParser()); +app.use(express.json()); +app.use(passport.initialize()); +app.use(router); +app.use("/download", express.static("uploads")); + +const corsOptions = { + //CORS 설정 및 whitelist로 'http://localhost:3000'을 설정 + origin: "http://localhost:3000", + optionSuccessStatus: 200, +}; + +app.use(cors(corsOptions)); + +app.use(errorHandler); + +app.listen(PORT, () => { + console.log(`Server is running on http://localhost:${PORT}`); +}); diff --git a/mission5/src/lib/constants.ts b/mission5/src/lib/constants.ts new file mode 100644 index 000000000..af8e48a99 --- /dev/null +++ b/mission5/src/lib/constants.ts @@ -0,0 +1,21 @@ +import dotenv from 'dotenv'; + +dotenv.config(); + +const NODE_ENV = process.env.NODE_ENV || 'development'; +const PORT = process.env.PORT || 3000; +const JWT_ACCESS_TOKEN_SECRET = + process.env.JWT_ACCESS_TOKEN_SECRET || 'your_jwt_access_token_secret'; +const JWT_REFRESH_TOKEN_SECRET = + process.env.JWT_REFRESH_TOKEN_SECRET || 'your_jwt_refresh_token_secret'; +const ACCESS_TOKEN_COOKIE_NAME = 'access-token'; +const REFRESH_TOKEN_COOKIE_NAME = 'refresh-token'; + +export { + NODE_ENV, + PORT, + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, + ACCESS_TOKEN_COOKIE_NAME, + REFRESH_TOKEN_COOKIE_NAME, +}; diff --git a/mission5/src/lib/passport/index.ts b/mission5/src/lib/passport/index.ts new file mode 100644 index 000000000..771eb1518 --- /dev/null +++ b/mission5/src/lib/passport/index.ts @@ -0,0 +1,9 @@ +import passport from 'passport'; +import { localStrategy } from './localStrategy'; +import { accessTokenStrategy, refreshTokenStrategy } from './jwtStrategy'; + +passport.use('local', localStrategy); +passport.use('access-token', accessTokenStrategy); +passport.use('refresh-token', refreshTokenStrategy); + +export default passport; diff --git a/mission5/src/lib/passport/jwtStrategy.ts b/mission5/src/lib/passport/jwtStrategy.ts new file mode 100644 index 000000000..7d258318c --- /dev/null +++ b/mission5/src/lib/passport/jwtStrategy.ts @@ -0,0 +1,45 @@ +import { Strategy as JwtStrategy } from 'passport-jwt'; +import prisma from '../prisma'; +import type { Request } from 'express'; +import type { VerifiedCallback } from 'passport-jwt'; +import { + ACCESS_TOKEN_COOKIE_NAME, + REFRESH_TOKEN_COOKIE_NAME, + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, +} from '../constants'; + +interface JwtPayload { + sub: number; +} + +const accessTokenOptions = { + jwtFromRequest: (req: Request) => req.cookies[ACCESS_TOKEN_COOKIE_NAME], + secretOrKey: JWT_ACCESS_TOKEN_SECRET, +}; + +const refreshTokenOptions = { + jwtFromRequest: (req: Request) => req.cookies[REFRESH_TOKEN_COOKIE_NAME], + secretOrKey: JWT_REFRESH_TOKEN_SECRET, +}; + +async function jwtVerify(payload: JwtPayload, done: VerifiedCallback) { + try { + const user = await prisma.user.findUnique({ + where: { id: payload.sub }, + }); + done(null, user); + } catch (error) { + done(error, false); + } +} + +export const accessTokenStrategy = new JwtStrategy( + accessTokenOptions, + jwtVerify +); + +export const refreshTokenStrategy = new JwtStrategy( + refreshTokenOptions, + jwtVerify +); diff --git a/mission5/src/lib/passport/localStrategy.ts b/mission5/src/lib/passport/localStrategy.ts new file mode 100644 index 000000000..3c3e7ba10 --- /dev/null +++ b/mission5/src/lib/passport/localStrategy.ts @@ -0,0 +1,27 @@ +import { Strategy as LocalStrategy } from "passport-local"; +import bcrypt from "bcrypt"; +import prisma from "../prisma"; + +export const localStrategy = new LocalStrategy( + { + usernameField: "email", // email을 localStrategy의 고정값 'username' 대신 쓰도록 지정 + passwordField: "password", + }, + async (email, password, done) => { + try { + const user = await prisma.user.findUnique({ where: { email } }); + if (!user) { + return done(null, false, { message: "No user found" }); + } + + const isPasswordValid = await bcrypt.compare(password, user.password); + if (!isPasswordValid) { + return done(null, false, { message: "Invalid password" }); + } + + return done(null, user); + } catch (err) { + return done(err); + } + } +); diff --git a/mission5/src/lib/prisma.ts b/mission5/src/lib/prisma.ts new file mode 100644 index 000000000..b904402d2 --- /dev/null +++ b/mission5/src/lib/prisma.ts @@ -0,0 +1,5 @@ +import { PrismaClient } from '@prisma/client'; + +const prisma = new PrismaClient(); + +export default prisma; \ No newline at end of file diff --git a/mission5/src/lib/token.ts b/mission5/src/lib/token.ts new file mode 100644 index 000000000..79a05e281 --- /dev/null +++ b/mission5/src/lib/token.ts @@ -0,0 +1,27 @@ +import jwt from 'jsonwebtoken'; +import { + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, +} from './constants'; + +function generateTokens(userId: number) { + const accessToken = jwt.sign({ sub: userId }, JWT_ACCESS_TOKEN_SECRET, { + expiresIn: '1h', + }); + const refreshToken = jwt.sign({ sub: userId }, JWT_REFRESH_TOKEN_SECRET, { + expiresIn: '1d', + }); + return { accessToken, refreshToken }; +} + +function verifyAccessToken(token: string) { + const decoded = jwt.verify(token, JWT_ACCESS_TOKEN_SECRET); + return { userId: decoded.sub }; +} + +function verifyRefreshToken(token: string) { + const decoded = jwt.verify(token, JWT_REFRESH_TOKEN_SECRET); + return { userId: decoded.sub }; +} + +export { generateTokens, verifyAccessToken, verifyRefreshToken }; diff --git a/mission5/src/middlewares/errorHandler.ts b/mission5/src/middlewares/errorHandler.ts new file mode 100644 index 000000000..dcaa5aaf3 --- /dev/null +++ b/mission5/src/middlewares/errorHandler.ts @@ -0,0 +1,22 @@ +import { z } from "zod"; +import httpStatus from "http-status"; +import express , { type Request, type Response, type NextFunction } from "express"; + +interface ExtendedError extends Error { + code?: string; +} + +export function errorHandler(err: ExtendedError, req: Request, res: Response, next: NextFunction) { + if (err instanceof z.ZodError) { + return res.status(httpStatus.BAD_REQUEST).json({ error: err.issues }); + } + + if (err.code === "P2025") { + return res.status(httpStatus.NOT_FOUND).json({ error: "Record not found" }); + } + + console.error("unhandled Error:", err); + return res + .status(httpStatus.INTERNAL_SERVER_ERROR) + .json({ error: "Internal Server Error" }); +} diff --git a/mission5/src/routers/articleRouter.ts b/mission5/src/routers/articleRouter.ts new file mode 100644 index 000000000..0ad073b08 --- /dev/null +++ b/mission5/src/routers/articleRouter.ts @@ -0,0 +1,203 @@ +import express, { type Request, type Response, type NextFunction } from "express"; +import prisma from "../lib/prisma"; +import passport from "../lib/passport/index"; +import { z } from "zod"; +import status from "http-status"; +import type { Prisma } from "@prisma/client"; + +const router = express.Router(); + +// body 검증 (게시글 생성/수정) +const articleSchema = z.object({ + title: z.string().min(1, { message: "제목을 입력해주세요" }), + content: z + .string() + .min(10, { message: "내용은 최소 10자 이상이어야 합니다." }) + .max(200, { message: "내용은 최대 200자까지 가능합니다." }) +}); + +// query 검증 (게시글 조회) +const articleQuerySchema = z.object({ + page: z + .string() + .default("1") + .transform(Number) + .refine((val) => val > 0, { message: "page는 1 이상의 정수여야 합니다." }), + pageSize: z + .string() + .default("5") + .transform(Number) + .refine((val) => val > 0 && val <= 100, { + message: "pageSize는 1~100 사이여야 합니다.", + }), + keyword: z.string().default(""), +}); + +router.post( + "/articles", + passport.authenticate("access-token", { session: false }), + createArticle +); +router.get("/articles", getArticles); +router.patch( + "/articles/:id", + passport.authenticate("access-token", { session: false }), + modifyArticle +); +router.delete( + "/articles/:id", + passport.authenticate("access-token", { session: false }), + deleteArticle +); +router.get( + "/articles/:id", + passport.authenticate("access-token", { session: false }), + getDetailArticle +); + +async function createArticle(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + const user = req.user; + const parsed = articleSchema.parse(req.body); + + try { + const article = await prisma.article.create({ + data: { + ...parsed, + userId: user.id, + }, + }); + + res.status(status.CREATED).json(article); + } catch (err) { + next(err); + } +} + +async function getArticles(req: Request, res: Response, next: NextFunction) { + const { page, pageSize, keyword } = articleQuerySchema.parse(req.query); + const where: Prisma.ArticleWhereInput = keyword //title과 content 에서 원하는 keyword가 있는 데이터를 찾도록 만든 변수 + ? { + OR: [ + { + title: { + contains: keyword, + mode: "insensitive", //대소문자 구분 없이 검색하기 위해 + }, + }, + { + content: { + contains: keyword, + mode: "insensitive", + }, + }, + ], + } + : {}; //기본값 {}으로 빈 객체를 수식하기 위함 + + try { + const articles = await prisma.article.findMany({ + skip: (page - 1) * pageSize, //offset pagination + take: pageSize, + orderBy: { + // 최신 순서대로 정렬하기(최신순) + createdAt: "desc", + }, + select: { + id: true, + title: true, + content: true, + createdAt: true, + }, + where, + }); + + res.status(status.OK).json(articles); + } catch (err) { + next(err); + } +} + +async function modifyArticle(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + const articleId = Number(req.params.id); + const parsed = articleSchema.parse(req.body); + const user = req.user; + + try { + const article = await prisma.article.findUnique({ + where: { id: articleId }, + }); + + if (!article) { + return res + .status(status.NOT_FOUND) + .json({ message: "Article not found" }); + } + if (article.userId !== user.id) { + return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + } + + const updated = await prisma.article.update({ + where: { id: articleId }, + data: { + ...parsed, + }, + }); + res.status(status.OK).json(updated); + } catch (err) { + next(err); + } +} + +async function deleteArticle(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + const articleId = Number(req.params.id); + const user = req.user; + + try { + const article = await prisma.article.findUnique({ + where: { id: articleId }, + }); + + if (!article) { + return res + .status(status.NOT_FOUND) + .json({ message: "Article not found" }); + } + if (article.userId !== user.id) { + return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + } + + await prisma.article.delete({ + where: { id: articleId }, + }); + res.status(status.NO_CONTENT).end(); + } catch (err) { + next(err); + } +} + +async function getDetailArticle(req: Request, res: Response, next: NextFunction) { + const articleId = Number(req.params.id); + + try { + const article = await prisma.article.findUnique({ + where: { id: articleId }, + select: { + id: true, + title: true, + content: true, + createdAt: true, + }, + }); + if (!article) { + return res.status(status.NOT_FOUND).json({ error: "Article not found" }); + } + res.status(status.OK).json(article); + } catch (err) { + next(err); + } +} + +export default router; diff --git a/mission5/src/routers/commentRouter.ts b/mission5/src/routers/commentRouter.ts new file mode 100644 index 000000000..28f9e0fc8 --- /dev/null +++ b/mission5/src/routers/commentRouter.ts @@ -0,0 +1,230 @@ +import express, { type Request, type Response, type NextFunction } from "express"; +import prisma from "../lib/prisma"; +import passport from "../lib/passport/index"; +import { z } from "zod"; +import status from "http-status"; + +const router = express.Router(); + +// body 검증 (댓글 생성/수정) +const commentSchema = z.object({ + content: z + .string() + .min(5, { message: "덧글은 최소 5자 이상이어야 합니다." }) + .max(100, { message: "덧글은 최대 100자까지 가능합니다." }), +}); + +const commentListSchema = z.object({ + id: z.coerce + .number() + .int() + .positive({ message: "id는 양의 정수여야 합니다." }), + lastId: z.coerce.number().int().positive().optional(), +}); + +router.post( + "/comments/products/:id", + passport.authenticate("access-token", { session: false }), + createProductComment +); +router.post( + "/comments/articles/:id", + passport.authenticate("access-token", { session: false }), + createArticleComment +); +router.patch( + "/comments/:id", + passport.authenticate("access-token", { session: false }), + modifyComment +); +router.delete( + "/comments/:id", + passport.authenticate("access-token", { session: false }), + deleteComment +); +router.get( + "/comments/products/:id", + passport.authenticate("access-token", { session: false }), + productCommentList +); +router.get( + "/comments/articles/:id", + passport.authenticate("access-token", { session: false }), + articleCommentList +); + +async function createProductComment(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + const productId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const user = req.user; + + try { + const comment = await prisma.comment.create({ + data: { + ...parsed, + productId, + articleId: null, + userId: user.id, + }, + }); + + res.status(status.CREATED).json(comment); + } catch (err) { + next(err); + } +} + +async function createArticleComment(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + const articleId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const user = req.user; + + try { + const comment = await prisma.comment.create({ + data: { + ...parsed, + productId: null, + articleId, + userId: user.id, + }, + }); + + res.status(status.CREATED).json(comment); + } catch (err) { + next(err); + } +} + +async function modifyComment(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + const commentId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const user = req.user; + + try { + const comment = await prisma.comment.findUnique({ + where: { id: commentId }, + }); + + if (!comment) { + return res + .status(status.NOT_FOUND) + .json({ message: "Comment not found" }); + } + if (comment.userId !== user.id) { + return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + } + + const updated = await prisma.comment.update({ + where: { id: commentId }, + data: { + ...parsed, + }, + }); + res.status(status.OK).json(updated); + } catch (err) { + next(err); + } +} + +async function deleteComment(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + const commentId = Number(req.params.id); + const user = req.user; + + try { + const comment = await prisma.comment.findUnique({ + where: { id: commentId }, + }); + + if (!comment) { + return res + .status(status.NOT_FOUND) + .json({ message: "Comment not found" }); + } + if (comment.userId !== user.id) { + return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + } + await prisma.comment.delete({ + where: { id: commentId }, + }); + + res.status(status.NO_CONTENT).end(); + } catch (err) { + next(err); + } +} + +async function productCommentList(req: Request, res: Response, next: NextFunction) { + try { + const parsed = commentListSchema.parse({ + id: req.params.id, + lastId: req.query.lastId, + }); + const { id: productId, lastId } = parsed; + + const comments = await prisma.comment.findMany({ + where: { + AND: [ + { + articleId: null, + }, + { + productId, + }, + ], + }, + take: 5, + skip: lastId ? 1 : 0, + ...(lastId && { cursor: { id: lastId } }), + select: { + id: true, + content: true, + createdAt: true, + }, + }); + + res.status(status.OK).json(comments); + } catch (err) { + next(err); + } +} + +async function articleCommentList(req: Request, res: Response, next: NextFunction) { + try { + const parsed = commentListSchema.parse({ + id: req.params.id, + lastId: req.query.lastId, + }); + const { id: articleId, lastId } = parsed; + + const comments = await prisma.comment.findMany({ + where: { + AND: [ + { + articleId, + }, + { + productId: null, + }, + ], + }, + take: 5, + skip: lastId ? 1 : 0, + ...(lastId && { cursor: { id: lastId } }), + select: { + id: true, + content: true, + createdAt: true, + }, + }); + + res.status(status.OK).json(comments); + } catch (err) { + next(err); + } +} + +export default router; diff --git a/mission5/src/routers/index.ts b/mission5/src/routers/index.ts new file mode 100644 index 000000000..589b90746 --- /dev/null +++ b/mission5/src/routers/index.ts @@ -0,0 +1,18 @@ +import express from 'express'; +import userRouter from './userRouter'; +import articleRouter from './articleRouter'; +import productRouter from './productRouter'; +import commentRouter from './commentRouter'; +import likeRouter from './likeRouter'; +import photoRouter from './photoRouter'; + +const router = express.Router(); + +router.use(userRouter); +router.use(articleRouter); +router.use(productRouter); +router.use(commentRouter); +router.use(likeRouter); +router.use(photoRouter); + +export default router; \ No newline at end of file diff --git a/mission5/src/routers/likeRouter.ts b/mission5/src/routers/likeRouter.ts new file mode 100644 index 000000000..d4f912d20 --- /dev/null +++ b/mission5/src/routers/likeRouter.ts @@ -0,0 +1,208 @@ +import express, { type Request, type Response, type NextFunction } from "express"; +import prisma from "../lib/prisma"; +import passport from "../lib/passport/index"; +import status from "http-status"; + +const router = express.Router(); + +router.post( + "/like/articles/:id", + passport.authenticate("access-token", { session: false }), + likeArticle +); +router.post( + "/like/products/:id", + passport.authenticate("access-token", { session: false }), + likeProduct +); +router.get( + "/like/articles", + passport.authenticate("access-token", { session: false }), + getLikedArticles +); +router.get( + "/like/products", + passport.authenticate("access-token", { session: false }), + getLikedProducts +); + +async function likeArticle(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + const user = req.user; + const articleId = Number(req.params.id); + + try { + const article = await prisma.article.findUnique({ + where: { id: articleId }, + }); + + if (!article) { + return res + .status(status.NOT_FOUND) + .json({ message: "Article not found" }); + } + const existing = await prisma.like.findUnique({ + where: { + userId_articleId: { userId: user.id, articleId }, + }, + }); + + if (existing) { + const updated = await prisma.like.update({ + where: { + userId_articleId: { userId: user.id, articleId }, + }, + data: { + like: !existing.like, + }, + }); + return res + .status(status.OK) + .json({ message: "Like toggled", isliked: updated.like }); + } else { + const created = await prisma.like.create({ + data: { + like: true, + articleId, + userId: user.id, + }, + }); + return res + .status(status.CREATED) + .json({ message: "Liked successfully", like: created.like }); + } + } catch (err) { + next(err); + } +} + +async function likeProduct(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + const user = req.user; + const productId = Number(req.params.id); + + try { + const product = await prisma.product.findUnique({ + where: { id: productId }, + }); + + if (!product) { + return res + .status(status.NOT_FOUND) + .json({ message: "Product not found" }); + } + + const existing = await prisma.like.findUnique({ + where: { + userId_productId: { userId: user.id, productId }, + }, + }); + + if (existing) { + const updated = await prisma.like.update({ + where: { + userId_productId: { userId: user.id, productId }, + }, + data: { + like: !existing.like, + }, + }); + return res + .status(status.OK) + .json({ message: "Like toggled", isLiked: updated.like }); + } else { + const created = await prisma.like.create({ + data: { + like: true, + productId, + userId: user.id, + }, + }); + return res + .status(status.CREATED) + .json({ message: "Liked successfully", isLiked: created.like }); + } + } catch (err) { + next(err); + } +} + +async function getLikedArticles(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + const user = req.user; + + try { + const likedArticles = await prisma.like.findMany({ + where: { + userId: user.id, + articleId: { not: null }, + like: true, + }, + include: { + article: { + select: { + id: true, + title: true, + }, + }, + }, + }); + + if (!likedArticles) { + return res + .status(status.NOT_FOUND) + .json({ message: "Articles not found" }); + } + + const articles = likedArticles.map((l) => ({ + ...l.article, + isLiked: true, + })); + + res.status(status.OK).json(articles); + } catch (err) { + next(err); + } +} + +async function getLikedProducts(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + const user = req.user; + + try { + const likedProducts = await prisma.like.findMany({ + where: { + userId: user.id, + productId: { not: null }, + like: true, + }, + include: { + product: { + select: { + id: true, + name: true, + price: true, + tags: true, + }, + }, + }, + }); + + if (!likedProducts) { + return res + .status(status.NOT_FOUND) + .json({ message: "Product not found" }); + } + + const products = likedProducts.map((l) => ({ + ...l.product, + isLiked: true, + })); + + res.status(status.OK).json(products); + } catch (err) { + next(err); + } +} + +export default router; diff --git a/mission5/src/routers/photoRouter.ts b/mission5/src/routers/photoRouter.ts new file mode 100644 index 000000000..12946d2b4 --- /dev/null +++ b/mission5/src/routers/photoRouter.ts @@ -0,0 +1,39 @@ +import express from "express"; +import multer from "multer"; +import passport from "../lib/passport/index"; +import prisma from "../lib/prisma"; +import status from "http-status"; + +const router = express.Router(); +const upload = multer({ dest: "uploads/" }); + +router.post( + "/users/photos", + passport.authenticate("access-token", { session: false }), + upload.single("image"), + async (req, res, next) => { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + const user = req.user; + + if (!req.file) { + return res.status(status.NOT_FOUND).json({ message: "No file upload" }); + } + + try { + const imageUrl = `/download/${req.file.filename}`; + const updatedUser = await prisma.user.update({ + where: { id: user.id }, + data: { image: imageUrl }, + }); + + res.status(status.OK).json({ + message: "Photo uploaded successfully", + image: updatedUser.image, + }); + } catch (err) { + next(err); + } + } +); + +export default router; diff --git a/mission5/src/routers/productRouter.ts b/mission5/src/routers/productRouter.ts new file mode 100644 index 000000000..0b28b891a --- /dev/null +++ b/mission5/src/routers/productRouter.ts @@ -0,0 +1,220 @@ +import express, { type Request, type Response, type NextFunction } from "express"; +import prisma from "../lib/prisma"; +import passport from "../lib/passport/index"; +import { z } from "zod"; +import status from "http-status"; +import type { Prisma } from "@prisma/client"; + +const router = express.Router(); + +// body 검증 (상품 생성/수정) +const productSchema = z.object({ + //유효성 검사 설정하기 + name: z.string().min(1, { message: "이름을 입력해주세요" }), + description: z + .string() + .min(10, { message: "설명은 최소 10자 이상이어야 합니다." }) + .max(100, { message: "설명은 최대 100자까지 가능합니다." }), + price: z.number().int() + .positive({ message: "가격은 양의 정수여야 합니다." }), + tags: z.string().default("") +}); + +// query 검증 (상품 조회) +const productQuerySchema = z.object({ + page: z + .string() + .default("1") + .transform(Number) + .refine((val) => val > 0, { message: "page는 1 이상의 정수여야 합니다." }), + pageSize: z + .string() + .default("5") + .transform(Number) + .refine((val) => val > 0 && val <= 100, { + message: "pageSize는 1~100 사이여야 합니다.", + }), + keyword: z.string().default(""), +}); + +router.post( + "/products", + passport.authenticate("access-token", { session: false }), + createProduct +); +router.get("/products", getProducts); +router.patch( + "/products/:id", + passport.authenticate("access-token", { session: false }), + modifyProduct +); +router.delete( + "/products/:id", + passport.authenticate("access-token", { session: false }), + deleteProduct +); +router.get( + "/products/:id", + passport.authenticate("access-token", { session: false }), + getDetailProduct +); + +async function createProduct(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + const parsed = productSchema.parse(req.body); + const user = req.user; + + try { + const createData = { + userId: user.id, + tags: parsed.tags, + ...(parsed.name && { name: parsed.name }), + ...(parsed.description && { description: parsed.description }), + ...(parsed.price && { price: parsed.price }), + } + const product = await prisma.product.create({ + data: { + ...parsed, + userId: req.user.id, // userId 추가 + }, + }); + + res.status(status.CREATED).json(product); + } catch (err) { + next(err); + } +} + +async function getProducts(req: Request, res: Response, next: NextFunction) { + const { page, pageSize, keyword } = productQuerySchema.parse(req.query); + const where: Prisma.ProductWhereInput = keyword //name과 description에서 원하는 keyword가 들어간 데이터를 찾도록 만든 변수 + ? { + OR: [ + { + name: { + contains: keyword, + mode: "insensitive" as const, //대소문자 구분 없이 검색하기 위해 + }, + }, + { + description: { + contains: keyword, + mode: "insensitive" as const, + }, + }, + ], + } + : {}; //기본값 {}으로 빈 객체를 수식하기 위함 + + try { + const products = await prisma.product.findMany({ + skip: (page - 1) * pageSize, + take: pageSize, + orderBy: { + // 최신 순서대로 정렬하기(최신순) + createdAt: "desc", + }, + select: { + id: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + where, + }); + + res.status(status.OK).json(products); + } catch (err) { + next(err); + } +} + +async function modifyProduct(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + const productId = Number(req.params.id); + const parsed = productSchema.parse(req.body); + const user = req.user; + + try { + const product = await prisma.product.findUnique({ + where: { id: productId }, + }); + + if (!product) { + return res + .status(status.NOT_FOUND) + .json({ message: "Product not found" }); + } + if (product.userId !== user.id) { + return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + } + + const updated = await prisma.product.update({ + where: { id: productId }, + data: { + ...parsed, + }, + }); + res.status(status.OK).json(updated); + } catch (err) { + next(err); + } +} + +async function deleteProduct(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + const productId = Number(req.params.id); + const user = req.user; + + try { + const product = await prisma.product.findUnique({ + where: { id: productId }, + }); + + if (!product) { + return res + .status(status.NOT_FOUND) + .json({ message: "Product not found" }); + } + if (product.userId !== user.id) { + return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + } + + await prisma.product.delete({ + where: { id: productId }, + }); + res.status(status.NO_CONTENT).end(); + } catch (err) { + next(err); + } +} + +async function getDetailProduct(req: Request, res: Response, next: NextFunction) { + const productId = Number(req.params.id); + + try { + const product = await prisma.product.findUnique({ + where: { id: productId }, + select: { + id: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + }); + + if (!product) { + return res.status(status.NOT_FOUND).json({ error: "Product not found" }); + } + + res.status(status.OK).json(product); + } catch (err) { + next(err); + } +} + +export default router; diff --git a/mission5/src/routers/userRouter.ts b/mission5/src/routers/userRouter.ts new file mode 100644 index 000000000..d9443e019 --- /dev/null +++ b/mission5/src/routers/userRouter.ts @@ -0,0 +1,227 @@ +import express, { Request, Response, NextFunction } from "express"; +import bcrypt from "bcrypt"; +import prisma from "../lib/prisma"; +import passport from "../lib/passport/index"; +import status from "http-status"; +import { generateTokens } from "../lib/token"; +import { + NODE_ENV, + ACCESS_TOKEN_COOKIE_NAME, + REFRESH_TOKEN_COOKIE_NAME, +} from "../lib/constants"; + +const router = express.Router(); + +router.post("/users/register", register); +router.post( + "/users/login", + passport.authenticate("local", { session: false }), + login +); +router.get( + "/users/profile", + passport.authenticate("access-token", { session: false }), + profile +); +router.patch( + "/users/modifyInformation", + passport.authenticate("access-token", { session: false }), + modifyinformation +); +router.patch( + "/users/modifyPassword", + passport.authenticate("access-token", { session: false }), + modifyPassword +); +router.get( + "/users/products", + passport.authenticate("access-token", { session: false }), + products +); +router.post( + "/users/refresh", + passport.authenticate("refresh-token", { session: false }), + refreshTokens +); +router.post("/users/logout", logout); + +async function register(req: Request, res: Response, next: NextFunction) { + const { email, nickname, password } = req.body; + + try { + const check = await prisma.user.findUnique({ where: { email } }); + if (check) { + return res + .status(status.CONFLICT) + .json({ message: "This ID already exists" }); + } + + const salt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(password, salt); + await prisma.user.create({ + data: { email, nickname, password: hashedPassword }, + }); + + res + .status(status.CREATED) + .json({ message: "User registered successfully" }); + } catch (err) { + next(err); + } +} + +function login(req: Request, res: Response, next: NextFunction) { + if (!req.user) { + return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + } + + try { + const { accessToken, refreshToken } = generateTokens(req.user.id); + setTokenCookies(res, accessToken, refreshToken); + res.status(status.OK).json({ token: accessToken, refreshToken }); + } catch (err) { + next(err); + } +} + +async function profile(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + + try { + const profile = await prisma.user.findUnique({ + where: { + id: req.user.id, + }, + select: { + id: true, + email: true, + nickname: true, + image: true, + createdAt: true, + updatedAt: true, + }, + }); + res.status(status.OK).json(profile); + } catch (err) { + next(err); + } +} + +async function modifyinformation(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + const { nickname, image } = req.body as { nickname?: string; image?: string }; + + try { + const updateData: Record = {}; + if (nickname) updateData.nickname = nickname; + if (image) updateData.image = image; + + if (Object.keys(updateData).length === 0) { + return res + .status(status.BAD_REQUEST) + .json({ message: "No update data provided" }); + } + + const updatedUser = await prisma.user.update({ + where: { id: req.user.id }, + data: updateData, + select: { + id: true, + email: true, + nickname: true, + image: true, + createdAt: true, + }, + }); + + res.status(status.OK).json({ + message: "User information updated successfully", + user: updatedUser, + }); + } catch (err) { + next(err); + } +} + +async function modifyPassword(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + const { password } = req.body; + + try { + const salt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(password, salt); + + await prisma.user.update({ + where: { id: req.user.id }, + data: { + password: hashedPassword, + }, + }); + + res + .status(status.OK) + .json({ message: "User passowrd updated successfully" }); + } catch (err) { + next(err); + } +} + +async function products(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + + try { + const products = await prisma.product.findMany({ + where: { + userId: req.user.id, + }, + select: { + name: true, + description: true, + price: true, + tags: true, + }, + }); + if (!products) { + return res.status(status.NOT_FOUND).json({ message: "No product" }); + } + res.status(status.OK).json(products); + } catch (err) { + next(err); + } +} + +function logout(req: Request, res: Response) { + clearTokenCookies(res); + res.status(status.OK).send({ message: "Logged out successfully" }); +} + +async function refreshTokens(req: Request, res: Response) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + + const { accessToken, refreshToken: newRefreshToken } = generateTokens( + req.user.id + ); + setTokenCookies(res, accessToken, newRefreshToken); + res.status(status.OK).send({ message: "Tokens refreshed" }); +} + +function setTokenCookies(res: Response, accessToken: string, refreshToken: string) { + res.cookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, { + httpOnly: true, + secure: NODE_ENV === "production", + maxAge: 1 * 60 * 60 * 1000, // 1 hour + }); + res.cookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken, { + httpOnly: true, + secure: NODE_ENV === "production", + maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days + path: "/users/refresh", + }); +} + +function clearTokenCookies(res: Response) { + res.clearCookie(ACCESS_TOKEN_COOKIE_NAME); + res.clearCookie(REFRESH_TOKEN_COOKIE_NAME); +} + +export default router; \ No newline at end of file diff --git a/mission5/src/types/express.d.ts b/mission5/src/types/express.d.ts new file mode 100644 index 000000000..c8caae71e --- /dev/null +++ b/mission5/src/types/express.d.ts @@ -0,0 +1,11 @@ +import type { User as PrismaUser } from "@prisma/client"; + +declare global { + namespace Express { + // Passport req.user 타입을 Prisma User로 확장 + interface User extends PrismaUser {} + } +} + +// 반드시 export {} 필요 +export {}; \ No newline at end of file diff --git a/mission5/tsconfig.json b/mission5/tsconfig.json new file mode 100644 index 000000000..e732234c0 --- /dev/null +++ b/mission5/tsconfig.json @@ -0,0 +1,48 @@ +{ + // Visit https://aka.ms/tsconfig to read more about this file + "compilerOptions": { + // File Layout + "rootDir": "./src", + "outDir": "./dist", + + // Environment Settings + // See also https://aka.ms/tsconfig/module + "module": "CommonJS", + "target": "ESNext", + // "types": [], + // For nodejs: + "lib": ["esnext"], + "types": ["node", "express", "passport"], + "allowJs": true, + "checkJs": true, + // and npm install -D @types/node + + // Other Outputs + "sourceMap": true, + "declaration": true, + "declarationMap": true, + + // Stricter Typechecking Options + "noUncheckedIndexedAccess": true, + "exactOptionalPropertyTypes": true, + + // Style Options + // "noImplicitReturns": true, + // "noImplicitOverride": true, + // "noUnusedLocals": true, + // "noUnusedParameters": true, + // "noFallthroughCasesInSwitch": true, + // "noPropertyAccessFromIndexSignature": true, + + // Recommended Options + "strict": true, + "jsx": "react-jsx", + "verbatimModuleSyntax": false, + "isolatedModules": true, + "noUncheckedSideEffectImports": true, + "moduleDetection": "force", + "skipLibCheck": true, + "esModuleInterop": true, + }, + "include": ["src/**/*", "src/types/**/*"] +} \ No newline at end of file diff --git a/mission5_dtos/.gitignore b/mission5_dtos/.gitignore new file mode 100644 index 000000000..9f62ec0b8 --- /dev/null +++ b/mission5_dtos/.gitignore @@ -0,0 +1,5 @@ +node_modules +# Keep environment variables out of version control +.env + +/generated/prisma diff --git a/mission5_dtos/package-lock.json b/mission5_dtos/package-lock.json new file mode 100644 index 000000000..4b76c5e8d --- /dev/null +++ b/mission5_dtos/package-lock.json @@ -0,0 +1,3128 @@ +{ + "name": "mission3", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mission3", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@prisma/client": "^6.13.0", + "bcrypt": "^6.0.0", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^17.2.2", + "express": "^5.1.0", + "http-status": "^2.1.0", + "multer": "^2.0.2", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", + "passport-local": "^1.0.0", + "tsx": "^4.20.5", + "zod": "^4.0.14" + }, + "devDependencies": { + "@types/bcrypt": "^6.0.0", + "@types/cookie-parser": "^1.4.9", + "@types/cors": "^2.8.19", + "@types/express": "^5.0.3", + "@types/jsonwebtoken": "^9.0.10", + "@types/multer": "^2.0.0", + "@types/node": "^24.3.1", + "@types/passport": "^1.0.17", + "@types/passport-jwt": "^4.0.1", + "@types/passport-local": "^1.0.38", + "prisma": "^6.15.0", + "ts-node": "^10.9.2", + "ts-node-dev": "^2.0.0", + "typescript": "^5.9.2" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@prisma/client": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.13.0.tgz", + "integrity": "sha512-8m2+I3dQovkV8CkDMluiwEV1TxV9EXdT6xaCz39O6jYw7mkf5gwfmi+cL4LJsEPwz5tG7sreBwkRpEMJedGYUQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "prisma": "*", + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@prisma/config": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.15.0.tgz", + "integrity": "sha512-KMEoec9b2u6zX0EbSEx/dRpx1oNLjqJEBZYyK0S3TTIbZ7GEGoVyGyFRk4C72+A38cuPLbfQGQvgOD+gBErKlA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "c12": "3.1.0", + "deepmerge-ts": "7.1.5", + "effect": "3.16.12", + "empathic": "2.0.0" + } + }, + "node_modules/@prisma/debug": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.15.0.tgz", + "integrity": "sha512-y7cSeLuQmyt+A3hstAs6tsuAiVXSnw9T55ra77z0nbNkA8Lcq9rNcQg6PI00by/+WnE/aMRJ/W7sZWn2cgIy1g==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.15.0.tgz", + "integrity": "sha512-opITiR5ddFJ1N2iqa7mkRlohCZqVSsHhRcc29QXeldMljOf4FSellLT0J5goVb64EzRTKcIDeIsJBgmilNcKxA==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/fetch-engine": "6.15.0", + "@prisma/get-platform": "6.15.0" + } + }, + "node_modules/@prisma/engines-version": { + "version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb.tgz", + "integrity": "sha512-a/46aK5j6L3ePwilZYEgYDPrhBQ/n4gYjLxT5YncUTJJNRnTCVjPF86QdzUOLRdYjCLfhtZp9aum90W0J+trrg==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.15.0.tgz", + "integrity": "sha512-xcT5f6b+OWBq6vTUnRCc7qL+Im570CtwvgSj+0MTSGA1o9UDSKZ/WANvwtiRXdbYWECpyC3CukoG3A04VTAPHw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/get-platform": "6.15.0" + } + }, + "node_modules/@prisma/get-platform": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.15.0.tgz", + "integrity": "sha512-Jbb+Xbxyp05NSR1x2epabetHiXvpO8tdN2YNoWoA/ZsbYyxxu/CO/ROBauIFuMXs3Ti+W7N7SJtWsHGaWte9Rg==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-/oJGukuH3D2+D+3H4JWLaAsJ/ji86dhRidzZ/Od7H/i8g+aCmvkeCc6Ni/f9uxGLSQVCRZkX2/lqEFG2BvWtlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie-parser": { + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.9.tgz", + "integrity": "sha512-tGZiZ2Gtc4m3wIdLkZ8mkj1T6CEHb35+VApbL2T14Dew8HA7c+04dmKqsKRNC+8RJPm16JEK0tFSwdZqubfc4g==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz", + "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", + "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/multer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz", + "integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/node": { + "version": "24.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz", + "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.10.0" + } + }, + "node_modules/@types/passport": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", + "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/passport-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-Y0Ykz6nWP4jpxgEUYq8NoVZeCQPo1ZndJLfapI249g1jHChvRfZRO/LS3tqu26YgAS/laI1qx98sYGz0IalRXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/jsonwebtoken": "*", + "@types/passport-strategy": "*" + } + }, + "node_modules/@types/passport-local": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.38.tgz", + "integrity": "sha512-nsrW4A963lYE7lNTv9cr5WmiUD1ibYJvWrpE13oxApFsRt77b0RdtZvKbCdNIY4v/QZ6TRQWaDDEwV1kCTmcXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-strategy": "*" + } + }, + "node_modules/@types/passport-strategy": { + "version": "0.2.38", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", + "integrity": "sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", + "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.8", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", + "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/strip-json-comments": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", + "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "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==", + "license": "MIT" + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.0", + "node-gyp-build": "^4.8.4" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "BSD-3-Clause" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/c12": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", + "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.3", + "confbox": "^0.2.2", + "defu": "^6.1.4", + "dotenv": "^16.6.1", + "exsolve": "^1.0.7", + "giget": "^2.0.0", + "jiti": "^2.4.2", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^1.0.0", + "pkg-types": "^2.2.0", + "rc9": "^2.1.2" + }, + "peerDependencies": { + "magicast": "^0.3.5" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } + } + }, + "node_modules/c12/node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "devOptional": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "consola": "^3.2.3" + } + }, + "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, + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "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, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deepmerge-ts": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", + "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dotenv": { + "version": "17.2.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", + "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/dynamic-dedupe": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", + "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + } + }, + "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==", + "license": "Apache-2.0", + "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", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/effect": { + "version": "3.16.12", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.16.12.tgz", + "integrity": "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "fast-check": "^3.23.1" + } + }, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/fast-check": { + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", + "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "dependencies": { + "pure-rand": "^6.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/giget": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", + "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.0", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.6", + "nypm": "^0.6.0", + "pathe": "^2.0.3" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "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/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, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-status": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-status/-/http-status-2.1.0.tgz", + "integrity": "sha512-O5kPr7AW7wYd/BBiOezTwnVAnmSNFY+J7hlZD2X5IOxVBetjcHAiTXhzj0gMrnojQlwy+UT1/Y3H3vJ3UlmvLA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 0.4.0" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "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==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/jiti": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", + "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "devOptional": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", + "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.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "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, + "license": "ISC" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.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, + "license": "ISC", + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/multer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", + "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", + "object-assign": "^4.1.1", + "type-is": "^1.6.18", + "xtend": "^4.0.2" + }, + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/multer/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-addon-api": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz", + "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nypm": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.1.tgz", + "integrity": "sha512-hlacBiRiv1k9hZFiphPUkfSQ/ZfQzZDzC+8z0wL3lvDAOUu/2NnChkKuMoMjNur/9OpKuz2QsIeiPVN0xM5Q0w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.2", + "pathe": "^2.0.3", + "pkg-types": "^2.2.0", + "tinyexec": "^1.0.1" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "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==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "license": "MIT", + "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-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", + "license": "MIT", + "dependencies": { + "jsonwebtoken": "^9.0.0", + "passport-strategy": "^1.0.0" + } + }, + "node_modules/passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "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-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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, + "node_modules/prisma": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.15.0.tgz", + "integrity": "sha512-E6RCgOt+kUVtjtZgLQDBJ6md2tDItLJNExwI0XJeBc1FKL+Vwb+ovxXxuok9r8oBgsOXBA33fGDuE/0qDdCWqQ==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/config": "6.15.0", + "@prisma/engines": "6.15.0" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc9": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", + "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "defu": "^6.1.4", + "destr": "^2.0.3" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "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" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tinyexec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", + "devOptional": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "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/ts-node-dev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz", + "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.1", + "dynamic-dedupe": "^0.3.0", + "minimist": "^1.2.6", + "mkdirp": "^1.0.4", + "resolve": "^1.0.0", + "rimraf": "^2.6.1", + "source-map-support": "^0.5.12", + "tree-kill": "^1.2.2", + "ts-node": "^10.4.0", + "tsconfig": "^7.0.0" + }, + "bin": { + "ts-node-dev": "lib/bin.js", + "tsnd": "lib/bin.js" + }, + "engines": { + "node": ">=0.8.0" + }, + "peerDependencies": { + "node-notifier": "*", + "typescript": "*" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/ts-node-dev/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "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" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/ts-node-dev/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-node-dev/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/tsconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", + "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/strip-bom": "^3.0.0", + "@types/strip-json-comments": "0.0.30", + "strip-bom": "^3.0.0", + "strip-json-comments": "^2.0.0" + } + }, + "node_modules/tsx": { + "version": "4.20.5", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.5.tgz", + "integrity": "sha512-+wKjMNU9w/EaQayHXb7WA7ZaHY6hN8WgfvHNQ3t1PnU91/7O8TcTnIhCDYTZwnt8JsO9IBqZ30Ln1r7pPF52Aw==", + "license": "MIT", + "dependencies": { + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "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==", + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/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, + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/zod": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.0.14.tgz", + "integrity": "sha512-nGFJTnJN6cM2v9kXL+SOBq3AtjQby3Mv5ySGFof5UGRHrRioSJ5iG680cYNjE/yWk671nROcpPj4hAS8nyLhSw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/mission5_dtos/package.json b/mission5_dtos/package.json new file mode 100644 index 000000000..a68267d04 --- /dev/null +++ b/mission5_dtos/package.json @@ -0,0 +1,49 @@ +{ + "name": "mission3", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "dev": "ts-node --files src/app.ts", + "start": "node dist/app.js", + "lint": "eslint . --ext .ts", + "prisma:generate": "prisma generate", + "prisma:migrate": "prisma migrate dev" + }, + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "@prisma/client": "^6.13.0", + "bcrypt": "^6.0.0", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^17.2.2", + "express": "^5.1.0", + "http-status": "^2.1.0", + "multer": "^2.0.2", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", + "passport-local": "^1.0.0", + "tsx": "^4.20.5", + "zod": "^4.0.14" + }, + "devDependencies": { + "@types/bcrypt": "^6.0.0", + "@types/cookie-parser": "^1.4.9", + "@types/cors": "^2.8.19", + "@types/express": "^5.0.3", + "@types/jsonwebtoken": "^9.0.10", + "@types/multer": "^2.0.0", + "@types/node": "^24.3.1", + "@types/passport": "^1.0.17", + "@types/passport-jwt": "^4.0.1", + "@types/passport-local": "^1.0.38", + "prisma": "^6.15.0", + "ts-node": "^10.9.2", + "ts-node-dev": "^2.0.0", + "typescript": "^5.9.2" + }, + "prisma": { + "seed": "node prisma/seed.js" + } +} diff --git a/mission5_dtos/prisma/migrations/20250904083711_test/migration.sql b/mission5_dtos/prisma/migrations/20250904083711_test/migration.sql new file mode 100644 index 000000000..ad7fbdc5d --- /dev/null +++ b/mission5_dtos/prisma/migrations/20250904083711_test/migration.sql @@ -0,0 +1,94 @@ +-- CreateTable +CREATE TABLE "public"."User" ( + "id" SERIAL NOT NULL, + "email" TEXT NOT NULL, + "nickname" TEXT NOT NULL, + "image" TEXT, + "password" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Product" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT NOT NULL, + "price" INTEGER NOT NULL, + "tags" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Product_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Article" ( + "id" SERIAL NOT NULL, + "title" TEXT NOT NULL, + "content" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Article_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Comment" ( + "id" SERIAL NOT NULL, + "content" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "productId" INTEGER, + "articleId" INTEGER, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Comment_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Like" ( + "id" SERIAL NOT NULL, + "like" BOOLEAN NOT NULL DEFAULT true, + "userId" INTEGER NOT NULL, + "productId" INTEGER, + "articleId" INTEGER, + + CONSTRAINT "Like_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "public"."User"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "Like_userId_productId_key" ON "public"."Like"("userId", "productId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Like_userId_articleId_key" ON "public"."Like"("userId", "articleId"); + +-- AddForeignKey +ALTER TABLE "public"."Product" ADD CONSTRAINT "Product_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Article" ADD CONSTRAINT "Article_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_productId_fkey" FOREIGN KEY ("productId") REFERENCES "public"."Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "public"."Article"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_productId_fkey" FOREIGN KEY ("productId") REFERENCES "public"."Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "public"."Article"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/mission5_dtos/prisma/migrations/migration_lock.toml b/mission5_dtos/prisma/migrations/migration_lock.toml new file mode 100644 index 000000000..044d57cdb --- /dev/null +++ b/mission5_dtos/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (e.g., Git) +provider = "postgresql" diff --git a/mission5_dtos/prisma/schema.prisma b/mission5_dtos/prisma/schema.prisma new file mode 100644 index 000000000..05365cc8e --- /dev/null +++ b/mission5_dtos/prisma/schema.prisma @@ -0,0 +1,75 @@ +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" +} + +model User { + id Int @id @default(autoincrement()) + email String @unique + nickname String + image String? + password String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + article Article[] + product Product[] + comment Comment[] + like Like[] +} + +model Product { + id Int @id @default(autoincrement()) + name String + description String + price Int + tags String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + comment Comment[] + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + like Like[] +} + +model Article { + id Int @id @default(autoincrement()) + title String + content String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + comment Comment[] + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + like Like[] +} + +model Comment { + id Int @id @default(autoincrement()) + content String + createdAt DateTime @default(now()) + productId Int? + product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) + articleId Int? + article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) +} + +model Like { + id Int @id @default(autoincrement()) + like Boolean @default(true) + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + productId Int? + product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) + articleId Int? + article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) + + // 유저-상품, 유저-게시글 각각 중복 방지, 좋아요 중첩 방지 + @@unique([userId, productId]) + @@unique([userId, articleId]) +} \ No newline at end of file diff --git a/mission5_dtos/src/app.ts b/mission5_dtos/src/app.ts new file mode 100644 index 000000000..9be0a16ce --- /dev/null +++ b/mission5_dtos/src/app.ts @@ -0,0 +1,31 @@ +import express from "express"; +import cookieParser from "cookie-parser"; +import router from "./routers/index"; +import { PORT } from "./lib/constants"; +import passport from "./lib/passport/index"; +import cors from "cors"; +import { errorHandler } from "./middlewares/errorHandler"; + +const app = express(); + +app.use(express.urlencoded({ extended: true })); + +app.use(express.json()); +app.use(cookieParser()); +const corsOptions = { + //CORS 설정 및 whitelist로 'http://localhost:3000'을 설정 + origin: "http://localhost:3000", + optionSuccessStatus: 200, +}; + +app.use(cors(corsOptions)); +app.use(passport.initialize()); +app.use(router); +app.use("/download", express.static("uploads")); + + +app.use(errorHandler); + +app.listen(PORT, () => { + console.log(`Server is running on http://localhost:${PORT}`); +}); diff --git a/mission5_dtos/src/controllers/articleController.ts b/mission5_dtos/src/controllers/articleController.ts new file mode 100644 index 000000000..0f7fa60a8 --- /dev/null +++ b/mission5_dtos/src/controllers/articleController.ts @@ -0,0 +1,102 @@ +import { Request, Response, NextFunction } from "express"; +import { z } from "zod"; +import status from "http-status"; +import { ArticleService } from "../services/articleService"; + +const articleService = new ArticleService(); + +// body 검증 (게시글 생성/수정) +const articleSchema = z.object({ + title: z.string().min(1, { message: "제목을 입력해주세요" }), + content: z + .string() + .min(10, { message: "내용은 최소 10자 이상이어야 합니다." }) + .max(200, { message: "내용은 최대 200자까지 가능합니다." }) +}); + +// PATCH용 스키마 (선택적) +const articleUpdateSchema = z.object({ + title: z.string().min(1, { message: "제목을 입력해주세요" }).optional(), + content: z + .string() + .min(10, { message: "내용은 최소 10자 이상이어야 합니다." }) + .max(200, { message: "내용은 최대 200자까지 가능합니다." }) + .optional(), +}); + +// query 검증 (게시글 조회) +const articleQuerySchema = z.object({ + page: z + .string() + .default("1") + .transform(Number) + .refine((val) => val > 0, { message: "page는 1 이상의 정수여야 합니다." }), + pageSize: z + .string() + .default("5") + .transform(Number) + .refine((val) => val > 0 && val <= 100, { + message: "pageSize는 1~100 사이여야 합니다.", + }), + keyword: z.string().default(""), +}); + +export class ArticleController { + async create(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = articleSchema.parse(req.body); + const article = await articleService.create(req.user.id, parsed); + res.status(status.CREATED).json(article); + } catch (err) { + next(err); + } + } + + async list(req: Request, res: Response, next: NextFunction) { + try { + const { page, pageSize, keyword } = articleQuerySchema.parse(req.query); + const articles = await articleService.list(page, pageSize, keyword); + res.status(status.OK).json(articles); + } catch (err) { + next(err); + } + } + + async detail(req: Request, res: Response, next: NextFunction) { + try { + const articleId = Number(req.params.id); + const article = await articleService.getDetail(articleId); + if (!article) return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + res.status(status.OK).json(article); + } catch (err) { + next(err); + } + } + + async update(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = articleUpdateSchema.parse(req.body) as { title?: string; content?: string }; + const articleId = Number(req.params.id); + const updated = await articleService.update(req.user.id, articleId, parsed); + res.status(status.OK).json(updated); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + async delete(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const articleId = Number(req.params.id); + await articleService.delete(req.user.id, articleId); + res.status(status.NO_CONTENT).end(); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } +} \ No newline at end of file diff --git a/mission5_dtos/src/controllers/commentController.ts b/mission5_dtos/src/controllers/commentController.ts new file mode 100644 index 000000000..652dd54f7 --- /dev/null +++ b/mission5_dtos/src/controllers/commentController.ts @@ -0,0 +1,90 @@ +import { Request, Response, NextFunction } from "express"; +import { z } from "zod"; +import status from "http-status"; +import { CommentService } from "../services/commentService"; + +const commentService = new CommentService(); + +// body 검증 +const commentSchema = z.object({ + content: z.string().min(5).max(100), +}); + +// query 검증 +const commentListSchema = z.object({ + id: z.coerce.number().int().positive(), + lastId: z.coerce.number().int().positive().optional(), +}); + +export class CommentController { + async createProductComment(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const productId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const comment = await commentService.createProductComment(req.user.id, productId, parsed.content); + res.status(status.CREATED).json(comment); + } catch (err) { + next(err); + } + } + + async createArticleComment(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const articleId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const comment = await commentService.createArticleComment(req.user.id, articleId, parsed.content); + res.status(status.CREATED).json(comment); + } catch (err) { + next(err); + } + } + + async modifyComment(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const commentId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const updated = await commentService.updateComment(req.user.id, commentId, parsed.content); + res.status(status.OK).json(updated); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Comment not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + + async deleteComment(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const commentId = Number(req.params.id); + await commentService.deleteComment(req.user.id, commentId); + res.status(status.NO_CONTENT).end(); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Comment not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + + async productCommentList(req: Request, res: Response, next: NextFunction) { + try { + const parsed = commentListSchema.parse({ id: req.params.id, lastId: req.query.lastId }); + const comments = await commentService.getProductComments(parsed.id, parsed.lastId); + res.status(status.OK).json(comments); + } catch (err) { + next(err); + } + } + + async articleCommentList(req: Request, res: Response, next: NextFunction) { + try { + const parsed = commentListSchema.parse({ id: req.params.id, lastId: req.query.lastId }); + const comments = await commentService.getArticleComments(parsed.id, parsed.lastId); + res.status(status.OK).json(comments); + } catch (err) { + next(err); + } + } +} \ No newline at end of file diff --git a/mission5_dtos/src/controllers/likeController.ts b/mission5_dtos/src/controllers/likeController.ts new file mode 100644 index 000000000..5e4c1edba --- /dev/null +++ b/mission5_dtos/src/controllers/likeController.ts @@ -0,0 +1,51 @@ +import { Request, Response, NextFunction } from "express"; +import status from "http-status"; +import { LikeService } from "../services/likeService"; + +const likeService = new LikeService(); + +export class LikeController { + async likeArticle(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const result = await likeService.likeArticle(req.user.id, Number(req.params.id)); + res.status(status.OK).json({ message: "Like toggled", isLiked: result.like }); + } catch (err: any) { + if (err.message === "ARTICLE_NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" }); + next(err); + } + } + + async likeProduct(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const result = await likeService.likeProduct(req.user.id, Number(req.params.id)); + res.status(status.OK).json({ message: "Like toggled", isLiked: result.like }); + } catch (err: any) { + if (err.message === "PRODUCT_NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + next(err); + } + } + + async getLikedArticles(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const likedArticles = await likeService.getLikedArticles(req.user.id); + const articles = likedArticles.map((l) => ({ ...l.article, isLiked: true })); + res.status(status.OK).json(articles); + } catch (err) { + next(err); + } + } + + async getLikedProducts(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const likedProducts = await likeService.getLikedProducts(req.user.id); + const products = likedProducts.map((l) => ({ ...l.product, isLiked: true })); + res.status(status.OK).json(products); + } catch (err) { + next(err); + } + } +} \ No newline at end of file diff --git a/mission5_dtos/src/controllers/photoController.ts b/mission5_dtos/src/controllers/photoController.ts new file mode 100644 index 000000000..0f52730ae --- /dev/null +++ b/mission5_dtos/src/controllers/photoController.ts @@ -0,0 +1,31 @@ +import { Request, Response, NextFunction } from "express"; +import prisma from "../lib/prisma"; +import status from "http-status"; + +export class PhotoController { + async upload(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + + if (!req.file) { + return res.status(status.BAD_REQUEST).json({ message: "No file uploaded" }); + } + + try { + // 파일 저장 위치 → 지금은 로컬, 나중에 S3 같은 외부 스토리지로 확장 가능 + const imageUrl = `/download/${req.file.filename}`; + + // 📌 기본 동작: 유저 프로필 업데이트 + const updatedUser = await prisma.user.update({ + where: { id: req.user.id }, + data: { image: imageUrl }, + }); + + res.status(status.OK).json({ + message: "Photo uploaded successfully", + image: updatedUser.image, + }); + } catch (err) { + next(err); + } + } +} \ No newline at end of file diff --git a/mission5_dtos/src/controllers/productController.ts b/mission5_dtos/src/controllers/productController.ts new file mode 100644 index 000000000..1f9a38e1b --- /dev/null +++ b/mission5_dtos/src/controllers/productController.ts @@ -0,0 +1,90 @@ +import { Request, Response, NextFunction } from "express"; +import { z } from "zod"; +import status from "http-status"; +import { ProductService } from "../services/productService"; + +const productService = new ProductService(); + +// body 검증(생성) +const productSchema = z.object({ + name: z.string().min(1, { message: "이름을 입력해주세요" }), + description: z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }), + price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }), + tags: z.string().default(""), +}); + +// body 검증(수정) +const productUpdateSchema = z.object({ + name: z.string().min(1, { message: "이름을 입력해주세요" }).optional(), + description: z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }).optional(), + price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }).optional(), + tags: z.string().default("").optional(), +}); + +// query 검증 +const productQuerySchema = z.object({ + page: z.string().default("1").transform(Number).refine((v) => v > 0), + pageSize: z.string().default("5").transform(Number).refine((v) => v > 0 && v <= 100), + keyword: z.string().default(""), +}); + +export class ProductController { + async create(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = productSchema.parse(req.body); + const product = await productService.create(req.user.id, parsed); + res.status(status.CREATED).json(product); + } catch (err) { + next(err); + } + } + + async list(req: Request, res: Response, next: NextFunction) { + try { + const { page, pageSize, keyword } = productQuerySchema.parse(req.query); + const products = await productService.list(page, pageSize, keyword); + res.status(status.OK).json(products); + } catch (err) { + next(err); + } + } + + async detail(req: Request, res: Response, next: NextFunction) { + try { + const productId = Number(req.params.id); + const product = await productService.getDetail(productId); + if (!product) return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + res.status(status.OK).json(product); + } catch (err) { + next(err); + } + } + + async update(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = productUpdateSchema.parse(req.body) as { name?: string; description?: string; price?: number; tags?: string; }; + const productId = Number(req.params.id); + const updated = await productService.update(req.user.id, productId, parsed); + res.status(status.OK).json(updated); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + + async delete(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const productId = Number(req.params.id); + await productService.delete(req.user.id, productId); + res.status(status.NO_CONTENT).end(); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } +} \ No newline at end of file diff --git a/mission5_dtos/src/controllers/userController.ts b/mission5_dtos/src/controllers/userController.ts new file mode 100644 index 000000000..d73a5ee30 --- /dev/null +++ b/mission5_dtos/src/controllers/userController.ts @@ -0,0 +1,89 @@ +import { Request, Response, NextFunction } from "express"; +import status from "http-status"; +import { UserService } from "../services/userService"; +import { setTokenCookies, clearTokenCookies } from "../lib/cookieUtil"; + +const userService = new UserService(); + +export class UserController { + async register(req: Request, res: Response, next: NextFunction) { + const { email, nickname, password } = req.body; + try { + const result = await userService.register(email, nickname, password); + res.status(status.CREATED).json(result); + } catch (err: any) { + if (err.message === "EMAIL_EXISTS") { + return res.status(status.CONFLICT).json({ message: "This ID already exists" }); + } + next(err); + } + } + + login(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + try { + const { accessToken, refreshToken } = userService.generateUserTokens(req.user.id); + setTokenCookies(res, accessToken, refreshToken); + res.status(status.OK).json({ token: accessToken, refreshToken }); + } catch (err) { + next(err); + } + } + + async profile(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const profile = await userService.getProfile(req.user.id); + res.status(status.OK).json(profile); + } catch (err) { + next(err); + } + } + + async modifyInformation(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const updatedUser = await userService.updateInformation(req.user.id, req.body.nickname, req.body.image); + res.status(status.OK).json({ message: "User information updated successfully", user: updatedUser }); + } catch (err: any) { + if (err.message === "NO_DATA") return res.status(status.BAD_REQUEST).json({ message: "No update data provided" }); + next(err); + } + } + + async modifyPassword(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const result = await userService.updatePassword(req.user.id, req.body.password); + res.status(status.OK).json(result); + } catch (err) { + next(err); + } + } + + async products(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const products = await userService.getProducts(req.user.id); + if (!products || products.length === 0) { + return res.status(status.NOT_FOUND).json({ message: "No product" }); + } + res.status(status.OK).json(products); + } catch (err) { + next(err); + } + } + + refreshTokens(req: Request, res: Response) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const { accessToken, refreshToken } = userService.generateUserTokens(req.user.id); + setTokenCookies(res, accessToken, refreshToken); + res.status(status.OK).send({ message: "Tokens refreshed" }); + } + + logout(req: Request, res: Response) { + clearTokenCookies(res); + res.status(status.OK).send({ message: "Logged out successfully" }); + } +} diff --git a/mission5_dtos/src/lib/constants.ts b/mission5_dtos/src/lib/constants.ts new file mode 100644 index 000000000..af8e48a99 --- /dev/null +++ b/mission5_dtos/src/lib/constants.ts @@ -0,0 +1,21 @@ +import dotenv from 'dotenv'; + +dotenv.config(); + +const NODE_ENV = process.env.NODE_ENV || 'development'; +const PORT = process.env.PORT || 3000; +const JWT_ACCESS_TOKEN_SECRET = + process.env.JWT_ACCESS_TOKEN_SECRET || 'your_jwt_access_token_secret'; +const JWT_REFRESH_TOKEN_SECRET = + process.env.JWT_REFRESH_TOKEN_SECRET || 'your_jwt_refresh_token_secret'; +const ACCESS_TOKEN_COOKIE_NAME = 'access-token'; +const REFRESH_TOKEN_COOKIE_NAME = 'refresh-token'; + +export { + NODE_ENV, + PORT, + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, + ACCESS_TOKEN_COOKIE_NAME, + REFRESH_TOKEN_COOKIE_NAME, +}; diff --git a/mission5_dtos/src/lib/cookieUtil.ts b/mission5_dtos/src/lib/cookieUtil.ts new file mode 100644 index 000000000..6d50ff83d --- /dev/null +++ b/mission5_dtos/src/lib/cookieUtil.ts @@ -0,0 +1,22 @@ +import { Response } from "express"; +import { ACCESS_TOKEN_COOKIE_NAME, REFRESH_TOKEN_COOKIE_NAME, NODE_ENV } from "./constants"; + +export function setTokenCookies(res: Response, accessToken: string, refreshToken: string) { + res.cookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, { + httpOnly: true, + secure: NODE_ENV === "production", + maxAge: 1 * 60 * 60 * 1000, // 1시간 + }); + + res.cookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken, { + httpOnly: true, + secure: NODE_ENV === "production", + maxAge: 7 * 24 * 60 * 60 * 1000, // 7일 + path: "/users/refresh", + }); +} + +export function clearTokenCookies(res: Response) { + res.clearCookie(ACCESS_TOKEN_COOKIE_NAME); + res.clearCookie(REFRESH_TOKEN_COOKIE_NAME); +} diff --git a/mission5_dtos/src/lib/passport/index.ts b/mission5_dtos/src/lib/passport/index.ts new file mode 100644 index 000000000..771eb1518 --- /dev/null +++ b/mission5_dtos/src/lib/passport/index.ts @@ -0,0 +1,9 @@ +import passport from 'passport'; +import { localStrategy } from './localStrategy'; +import { accessTokenStrategy, refreshTokenStrategy } from './jwtStrategy'; + +passport.use('local', localStrategy); +passport.use('access-token', accessTokenStrategy); +passport.use('refresh-token', refreshTokenStrategy); + +export default passport; diff --git a/mission5_dtos/src/lib/passport/jwtStrategy.ts b/mission5_dtos/src/lib/passport/jwtStrategy.ts new file mode 100644 index 000000000..7d258318c --- /dev/null +++ b/mission5_dtos/src/lib/passport/jwtStrategy.ts @@ -0,0 +1,45 @@ +import { Strategy as JwtStrategy } from 'passport-jwt'; +import prisma from '../prisma'; +import type { Request } from 'express'; +import type { VerifiedCallback } from 'passport-jwt'; +import { + ACCESS_TOKEN_COOKIE_NAME, + REFRESH_TOKEN_COOKIE_NAME, + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, +} from '../constants'; + +interface JwtPayload { + sub: number; +} + +const accessTokenOptions = { + jwtFromRequest: (req: Request) => req.cookies[ACCESS_TOKEN_COOKIE_NAME], + secretOrKey: JWT_ACCESS_TOKEN_SECRET, +}; + +const refreshTokenOptions = { + jwtFromRequest: (req: Request) => req.cookies[REFRESH_TOKEN_COOKIE_NAME], + secretOrKey: JWT_REFRESH_TOKEN_SECRET, +}; + +async function jwtVerify(payload: JwtPayload, done: VerifiedCallback) { + try { + const user = await prisma.user.findUnique({ + where: { id: payload.sub }, + }); + done(null, user); + } catch (error) { + done(error, false); + } +} + +export const accessTokenStrategy = new JwtStrategy( + accessTokenOptions, + jwtVerify +); + +export const refreshTokenStrategy = new JwtStrategy( + refreshTokenOptions, + jwtVerify +); diff --git a/mission5_dtos/src/lib/passport/localStrategy.ts b/mission5_dtos/src/lib/passport/localStrategy.ts new file mode 100644 index 000000000..3c3e7ba10 --- /dev/null +++ b/mission5_dtos/src/lib/passport/localStrategy.ts @@ -0,0 +1,27 @@ +import { Strategy as LocalStrategy } from "passport-local"; +import bcrypt from "bcrypt"; +import prisma from "../prisma"; + +export const localStrategy = new LocalStrategy( + { + usernameField: "email", // email을 localStrategy의 고정값 'username' 대신 쓰도록 지정 + passwordField: "password", + }, + async (email, password, done) => { + try { + const user = await prisma.user.findUnique({ where: { email } }); + if (!user) { + return done(null, false, { message: "No user found" }); + } + + const isPasswordValid = await bcrypt.compare(password, user.password); + if (!isPasswordValid) { + return done(null, false, { message: "Invalid password" }); + } + + return done(null, user); + } catch (err) { + return done(err); + } + } +); diff --git a/mission5_dtos/src/lib/prisma.ts b/mission5_dtos/src/lib/prisma.ts new file mode 100644 index 000000000..b904402d2 --- /dev/null +++ b/mission5_dtos/src/lib/prisma.ts @@ -0,0 +1,5 @@ +import { PrismaClient } from '@prisma/client'; + +const prisma = new PrismaClient(); + +export default prisma; \ No newline at end of file diff --git a/mission5_dtos/src/lib/token.ts b/mission5_dtos/src/lib/token.ts new file mode 100644 index 000000000..79a05e281 --- /dev/null +++ b/mission5_dtos/src/lib/token.ts @@ -0,0 +1,27 @@ +import jwt from 'jsonwebtoken'; +import { + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, +} from './constants'; + +function generateTokens(userId: number) { + const accessToken = jwt.sign({ sub: userId }, JWT_ACCESS_TOKEN_SECRET, { + expiresIn: '1h', + }); + const refreshToken = jwt.sign({ sub: userId }, JWT_REFRESH_TOKEN_SECRET, { + expiresIn: '1d', + }); + return { accessToken, refreshToken }; +} + +function verifyAccessToken(token: string) { + const decoded = jwt.verify(token, JWT_ACCESS_TOKEN_SECRET); + return { userId: decoded.sub }; +} + +function verifyRefreshToken(token: string) { + const decoded = jwt.verify(token, JWT_REFRESH_TOKEN_SECRET); + return { userId: decoded.sub }; +} + +export { generateTokens, verifyAccessToken, verifyRefreshToken }; diff --git a/mission5_dtos/src/middlewares/errorHandler.ts b/mission5_dtos/src/middlewares/errorHandler.ts new file mode 100644 index 000000000..dcaa5aaf3 --- /dev/null +++ b/mission5_dtos/src/middlewares/errorHandler.ts @@ -0,0 +1,22 @@ +import { z } from "zod"; +import httpStatus from "http-status"; +import express , { type Request, type Response, type NextFunction } from "express"; + +interface ExtendedError extends Error { + code?: string; +} + +export function errorHandler(err: ExtendedError, req: Request, res: Response, next: NextFunction) { + if (err instanceof z.ZodError) { + return res.status(httpStatus.BAD_REQUEST).json({ error: err.issues }); + } + + if (err.code === "P2025") { + return res.status(httpStatus.NOT_FOUND).json({ error: "Record not found" }); + } + + console.error("unhandled Error:", err); + return res + .status(httpStatus.INTERNAL_SERVER_ERROR) + .json({ error: "Internal Server Error" }); +} diff --git a/mission5_dtos/src/repositories/articleRepository.ts b/mission5_dtos/src/repositories/articleRepository.ts new file mode 100644 index 000000000..12e328cbc --- /dev/null +++ b/mission5_dtos/src/repositories/articleRepository.ts @@ -0,0 +1,44 @@ +import prisma from "../lib/prisma"; +import { Prisma } from "@prisma/client"; + +export class ArticleRepository { + async createArticle(data: { userId: number, title: string, content: string }) { + return prisma.article.create({ data }); + } + + async findMany(where: Prisma.ArticleWhereInput, skip: number, take: number) { + return prisma.article.findMany({ + skip, + take, + orderBy: { createdAt: "desc" }, + select: { + id: true, + title: true, + content: true, + createdAt: true, + }, + where, + }); + } + + async findById(id: number) { + return prisma.article.findUnique({ + where: { id }, + select: { + id: true, + userId: true, + title: true, + content: true, + createdAt: true, + }, + }); + } + + async updatedArticle(id: number, data: Partial<{ title: string, content: string }>) { + return prisma.article.update({ where: { id }, data }); + } + + async deleteArticle(id: number) { + return prisma.article.delete({ where: { id } }); + } +} \ No newline at end of file diff --git a/mission5_dtos/src/repositories/commentRepository.ts b/mission5_dtos/src/repositories/commentRepository.ts new file mode 100644 index 000000000..028695d4a --- /dev/null +++ b/mission5_dtos/src/repositories/commentRepository.ts @@ -0,0 +1,50 @@ +import prisma from "../lib/prisma"; + +export class CommentRepository { + async createProductComment(userId: number, productId: number, content: string) { + return prisma.comment.create({ + data: { content, productId, articleId: null, userId }, + }); + } + + async createArticleComment(userId: number, articleId: number, content: string) { + return prisma.comment.create({ + data: { content, productId: null, articleId, userId }, + }); + } + + async findById(commentId: number) { + return prisma.comment.findUnique({ where: { id: commentId } }); + } + + async updateComment(commentId: number, content: string) { + return prisma.comment.update({ + where: { id: commentId }, + data: { content }, + }); + } + + async deleteComment(commentId: number) { + return prisma.comment.delete({ where: { id: commentId } }); + } + + async findProductComments(productId: number, lastId?: number) { + return prisma.comment.findMany({ + where: { articleId: null, productId }, + take: 5, + skip: lastId ? 1 : 0, + ...(lastId && { cursor: { id: lastId } }), + select: { id: true, content: true, createdAt: true }, + }); + } + + async findArticleComments(articleId: number, lastId?: number) { + return prisma.comment.findMany({ + where: { articleId, productId: null }, + take: 5, + skip: lastId ? 1 : 0, + ...(lastId && { cursor: { id: lastId } }), + select: { id: true, content: true, createdAt: true }, + }); + } +} \ No newline at end of file diff --git a/mission5_dtos/src/repositories/likeRepository.ts b/mission5_dtos/src/repositories/likeRepository.ts new file mode 100644 index 000000000..f2b154b8f --- /dev/null +++ b/mission5_dtos/src/repositories/likeRepository.ts @@ -0,0 +1,67 @@ +import prisma from "../lib/prisma"; + +export class LikeRepository { + async findArticle(articleId: number) { + return prisma.article.findUnique({ where: { id: articleId } }); + } + + async findProduct(productId: number) { + return prisma.product.findUnique({ where: { id: productId } }); + } + + async findArticleLike(userId: number, articleId: number) { + return prisma.like.findUnique({ + where: { userId_articleId: { userId, articleId } }, + }); + } + + async findProductLike(userId: number, productId: number) { + return prisma.like.findUnique({ + where: { userId_productId: { userId, productId } }, + }); + } + + async toggleArticleLike(userId: number, articleId: number, current: boolean) { + return prisma.like.update({ + where: { userId_articleId: { userId, articleId } }, + data: { like: !current }, + }); + } + + async toggleProductLike(userId: number, productId: number, current: boolean) { + return prisma.like.update({ + where: { userId_productId: { userId, productId } }, + data: { like: !current }, + }); + } + + async createArticleLike(userId: number, articleId: number) { + return prisma.like.create({ + data: { like: true, userId, articleId }, + }); + } + + async createProductLike(userId: number, productId: number) { + return prisma.like.create({ + data: { like: true, userId, productId }, + }); + } + + async findLikedArticles(userId: number) { + return prisma.like.findMany({ + where: { userId, articleId: { not: null }, like: true }, + include: { + article: { select: { id: true, title: true } }, + }, + }); + } + + async findLikedProducts(userId: number) { + return prisma.like.findMany({ + where: { userId, productId: { not: null }, like: true }, + include: { + product: { select: { id: true, name: true, price: true, tags: true } }, + }, + }); + } +} \ No newline at end of file diff --git a/mission5_dtos/src/repositories/productRepository.ts b/mission5_dtos/src/repositories/productRepository.ts new file mode 100644 index 000000000..21f7475ca --- /dev/null +++ b/mission5_dtos/src/repositories/productRepository.ts @@ -0,0 +1,48 @@ +import prisma from "../lib/prisma"; +import { Prisma } from "@prisma/client"; + +export class ProductRepository { + async createProduct(data: { userId: number; name: string; description: string; price: number; tags: string }) { + return prisma.product.create({ data }); + } + + async findMany(where: Prisma.ProductWhereInput, skip: number, take: number) { + return prisma.product.findMany({ + skip, + take, + orderBy: { createdAt: "desc" }, + select: { + id: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + where, + }); + } + + async findById(id: number) { + return prisma.product.findUnique({ + where: { id }, + select: { + id: true, + userId: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + }); + } + + async updateProduct(id: number, data: Partial<{ name: string; description: string; price: number; tags: string }>) { + return prisma.product.update({ where: { id }, data }); + } + + async deleteProduct(id: number) { + return prisma.product.delete({ where: { id } }); + } +} \ No newline at end of file diff --git a/mission5_dtos/src/repositories/userRepository.ts b/mission5_dtos/src/repositories/userRepository.ts new file mode 100644 index 000000000..e2eb38b76 --- /dev/null +++ b/mission5_dtos/src/repositories/userRepository.ts @@ -0,0 +1,29 @@ +import prisma from "../lib/prisma"; + +export class UserRepository { + async findByEmail(email: string) { + return prisma.user.findUnique({ where: { email } }); + } + + async findById(id: number) { + return prisma.user.findUnique({ + where: { id }, + select: { id: true, email: true, nickname: true, image: true, createdAt: true, updatedAt: true }, + }); + } + + async createUser(email: string, nickname: string, password: string) { + return prisma.user.create({ data: { email, nickname, password } }); + } + + async updateUser(id: number, data: Partial<{ nickname: string; image: string; password: string }>) { + return prisma.user.update({ where: { id }, data }); + } + + async findProductsByUserId(userId: number) { + return prisma.product.findMany({ + where: { userId }, + select: { name: true, description: true, price: true, tags: true }, + }); + } +} \ No newline at end of file diff --git a/mission5_dtos/src/routers/articleRouter.ts b/mission5_dtos/src/routers/articleRouter.ts new file mode 100644 index 000000000..4c4161a6b --- /dev/null +++ b/mission5_dtos/src/routers/articleRouter.ts @@ -0,0 +1,14 @@ +import express from "express"; +import passport from "../lib/passport"; +import { ArticleController } from "../controllers/articleController"; + +const router = express.Router(); +const controller = new ArticleController(); + +router.post("/", passport.authenticate("access-token", { session: false }), controller.create); +router.get("/", passport.authenticate("access-token", { session: false }), controller.list); +router.get("/:id", passport.authenticate("access-token", { session: false }), controller.detail); +router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update); +router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete); + +export default router; \ No newline at end of file diff --git a/mission5_dtos/src/routers/commentRouter.ts b/mission5_dtos/src/routers/commentRouter.ts new file mode 100644 index 000000000..f7b6b4903 --- /dev/null +++ b/mission5_dtos/src/routers/commentRouter.ts @@ -0,0 +1,15 @@ +import express from "express"; +import passport from "../lib/passport"; +import { CommentController } from "../controllers/commentController"; + +const router = express.Router(); +const controller = new CommentController(); + +router.post("/products/:id", passport.authenticate("access-token", { session: false }), controller.createProductComment); +router.post("/articles/:id", passport.authenticate("access-token", { session: false }), controller.createArticleComment); +router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.modifyComment); +router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.deleteComment); +router.get("/products/:id", passport.authenticate("access-token", { session: false }), controller.productCommentList); +router.get("/articles/:id", passport.authenticate("access-token", { session: false }), controller.articleCommentList); + +export default router; \ No newline at end of file diff --git a/mission5_dtos/src/routers/index.ts b/mission5_dtos/src/routers/index.ts new file mode 100644 index 000000000..c1bafd4f0 --- /dev/null +++ b/mission5_dtos/src/routers/index.ts @@ -0,0 +1,19 @@ +import express from "express"; + +import userRouter from "./userRouter"; +import articleRouter from "./articleRouter"; +import productRouter from "./productRouter"; +import commentRouter from "./commentRouter"; +import likeRouter from "./likeRouter"; +import photoRouter from "./photoRouter"; // ✅ 공통 업로드 전용 + +const router = express.Router(); + +router.use("/users", userRouter); +router.use("/articles", articleRouter); +router.use("/products", productRouter); +router.use("/comments", commentRouter); +router.use("/likes", likeRouter); +router.use(photoRouter); // 📌 prefix는 /photos + +export default router; \ No newline at end of file diff --git a/mission5_dtos/src/routers/likeRouter.ts b/mission5_dtos/src/routers/likeRouter.ts new file mode 100644 index 000000000..10ec9924d --- /dev/null +++ b/mission5_dtos/src/routers/likeRouter.ts @@ -0,0 +1,13 @@ +import express from "express"; +import passport from "../lib/passport"; +import { LikeController } from "../controllers/likeController"; + +const router = express.Router(); +const controller = new LikeController(); + +router.post("/articles/:id", passport.authenticate("access-token", { session: false }), controller.likeArticle); +router.post("/products/:id", passport.authenticate("access-token", { session: false }), controller.likeProduct); +router.get("/articles", passport.authenticate("access-token", { session: false }), controller.getLikedArticles); +router.get("/products", passport.authenticate("access-token", { session: false }), controller.getLikedProducts); + +export default router; \ No newline at end of file diff --git a/mission5_dtos/src/routers/photoRouter.ts b/mission5_dtos/src/routers/photoRouter.ts new file mode 100644 index 000000000..036f69e1a --- /dev/null +++ b/mission5_dtos/src/routers/photoRouter.ts @@ -0,0 +1,18 @@ +import express from "express"; +import multer from "multer"; +import passport from "../lib/passport"; +import { PhotoController } from "../controllers/photoController"; + +const router = express.Router(); +const upload = multer({ dest: "uploads/" }); +const controller = new PhotoController(); + +// ✅ 공통 업로드 엔드포인트 +router.post( + "/", + passport.authenticate("access-token", { session: false }), + upload.single("image"), + controller.upload +); + +export default router; diff --git a/mission5_dtos/src/routers/productRouter.ts b/mission5_dtos/src/routers/productRouter.ts new file mode 100644 index 000000000..63f2d5d87 --- /dev/null +++ b/mission5_dtos/src/routers/productRouter.ts @@ -0,0 +1,14 @@ +import express from "express"; +import passport from "../lib/passport"; +import { ProductController } from "../controllers/productController"; + +const router = express.Router(); +const controller = new ProductController(); + +router.post("/", passport.authenticate("access-token", { session: false }), controller.create); +router.get("/", controller.list); +router.get("/:id", passport.authenticate("access-token", { session: false }), controller.list); +router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update); +router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete); + +export default router; \ No newline at end of file diff --git a/mission5_dtos/src/routers/userRouter.ts b/mission5_dtos/src/routers/userRouter.ts new file mode 100644 index 000000000..0df2f4317 --- /dev/null +++ b/mission5_dtos/src/routers/userRouter.ts @@ -0,0 +1,17 @@ +import express from "express"; +import passport from "../lib/passport"; +import { UserController } from "../controllers/userController"; + +const router = express.Router(); +const controller = new UserController(); + +router.post("/register", controller.register); +router.post("/login", passport.authenticate("local", { session: false }), controller.login); +router.get("/profile", passport.authenticate("access-token", { session: false }), controller.profile); +router.patch("/modifyInformation", passport.authenticate("access-token", { session: false }), controller.modifyInformation); +router.patch("/modifyPassword", passport.authenticate("access-token", { session: false }), controller.modifyPassword); +router.get("/products", passport.authenticate("access-token", { session: false }), controller.products); +router.post("/refresh", passport.authenticate("refresh-token", { session: false }), controller.refreshTokens); +router.post("/logout", controller.logout); + +export default router; diff --git a/mission5_dtos/src/services/articleService.ts b/mission5_dtos/src/services/articleService.ts new file mode 100644 index 000000000..8df8210d4 --- /dev/null +++ b/mission5_dtos/src/services/articleService.ts @@ -0,0 +1,46 @@ +import { ArticleRepository } from "../repositories/articleRepository"; +import type { Prisma } from "@prisma/client"; + +export class ArticleService { + private repo = new ArticleRepository(); + + async create(userId: number, data: { title: string; content: string }) { + return this.repo.createArticle({ ...data, userId }); + } + + async list(page: number, pageSize: number, keyword: string) { + const where: Prisma.ArticleWhereInput = keyword + ? { + OR: [ + { title: { contains: keyword, mode: "insensitive" } }, + { content: { contains: keyword, mode: "insensitive" } }, + ], + } + : {}; + return this.repo.findMany(where, (page - 1) * pageSize, pageSize); + } + + async getDetail(id: number) { + return this.repo.findById(id); + } + + async update( + userId: number, + articleId: number, + data: { title?: string; content?: string; } + ) { + const article = await this.repo.findById(articleId); + if (!article) throw new Error("NOT_FOUND"); + if (article.userId !== userId) throw new Error("FORBIDDEN"); + + return this.repo.updatedArticle(articleId, data); + } + + async delete(userId: number, articleId: number) { + const article = await this.repo.findById(articleId); + if (!article) throw new Error("NOT_FOUND"); + if (article.userId !== userId) throw new Error("FORBIDDEN"); + + await this.repo.deleteArticle(articleId); + } +} diff --git a/mission5_dtos/src/services/commentService.ts b/mission5_dtos/src/services/commentService.ts new file mode 100644 index 000000000..a1b7a218f --- /dev/null +++ b/mission5_dtos/src/services/commentService.ts @@ -0,0 +1,35 @@ +import { CommentRepository } from "../repositories/commentRepository"; + +export class CommentService { + private repo = new CommentRepository(); + + async createProductComment(userId: number, productId: number, content: string) { + return this.repo.createProductComment(userId, productId, content); + } + + async createArticleComment(userId: number, articleId: number, content: string) { + return this.repo.createArticleComment(userId, articleId, content); + } + + async updateComment(userId: number, commentId: number, content: string) { + const comment = await this.repo.findById(commentId); + if (!comment) throw new Error("NOT_FOUND"); + if (comment.userId !== userId) throw new Error("FORBIDDEN"); + return this.repo.updateComment(commentId, content); + } + + async deleteComment(userId: number, commentId: number) { + const comment = await this.repo.findById(commentId); + if (!comment) throw new Error("NOT_FOUND"); + if (comment.userId !== userId) throw new Error("FORBIDDEN"); + await this.repo.deleteComment(commentId); + } + + async getProductComments(productId: number, lastId?: number) { + return this.repo.findProductComments(productId, lastId); + } + + async getArticleComments(articleId: number, lastId?: number) { + return this.repo.findArticleComments(articleId, lastId); + } +} diff --git a/mission5_dtos/src/services/likeService.ts b/mission5_dtos/src/services/likeService.ts new file mode 100644 index 000000000..4f7118e7f --- /dev/null +++ b/mission5_dtos/src/services/likeService.ts @@ -0,0 +1,35 @@ +import { LikeRepository } from "../repositories/likeRepository"; + +export class LikeService { + private repo = new LikeRepository(); + + async likeArticle(userId: number, articleId: number) { + const article = await this.repo.findArticle(articleId); + if (!article) throw new Error("ARTICLE_NOT_FOUND"); + + const existing = await this.repo.findArticleLike(userId, articleId); + if (existing) { + return this.repo.toggleArticleLike(userId, articleId, existing.like); + } + return this.repo.createArticleLike(userId, articleId); + } + + async likeProduct(userId: number, productId: number) { + const product = await this.repo.findProduct(productId); + if (!product) throw new Error("PRODUCT_NOT_FOUND"); + + const existing = await this.repo.findProductLike(userId, productId); + if (existing) { + return this.repo.toggleProductLike(userId, productId, existing.like); + } + return this.repo.createProductLike(userId, productId); + } + + async getLikedArticles(userId: number) { + return this.repo.findLikedArticles(userId); + } + + async getLikedProducts(userId: number) { + return this.repo.findLikedProducts(userId); + } +} \ No newline at end of file diff --git a/mission5_dtos/src/services/productService.ts b/mission5_dtos/src/services/productService.ts new file mode 100644 index 000000000..62780c6b3 --- /dev/null +++ b/mission5_dtos/src/services/productService.ts @@ -0,0 +1,42 @@ +import { ProductRepository } from "../repositories/productRepository"; +import type { Prisma } from "@prisma/client"; + +export class ProductService { + private repo = new ProductRepository(); + + async create(userId: number, data: { name: string; description: string; price: number; tags: string }) { + return this.repo.createProduct({ ...data, userId }); + } + + async list(page: number, pageSize: number, keyword: string) { + const where: Prisma.ProductWhereInput = keyword + ? { + OR: [ + { name: { contains: keyword, mode: "insensitive" } }, + { description: { contains: keyword, mode: "insensitive" } }, + ], + } + : {}; + return this.repo.findMany(where, (page - 1) * pageSize, pageSize); + } + + async getDetail(id: number) { + return this.repo.findById(id); + } + + async update(userId: number, productId: number, data: { name?: string; description?: string; price?: number; tags?: string; }) { + const product = await this.repo.findById(productId); + if (!product) throw new Error("NOT_FOUND"); + if (product.userId !== userId) throw new Error("FORBIDDEN"); + + return this.repo.updateProduct(productId, data); + } + + async delete(userId: number, productId: number) { + const product = await this.repo.findById(productId); + if (!product) throw new Error("NOT_FOUND"); + if (product.userId !== userId) throw new Error("FORBIDDEN"); + + await this.repo.deleteProduct(productId); + } +} \ No newline at end of file diff --git a/mission5_dtos/src/services/userService.ts b/mission5_dtos/src/services/userService.ts new file mode 100644 index 000000000..5294115cb --- /dev/null +++ b/mission5_dtos/src/services/userService.ts @@ -0,0 +1,47 @@ +import bcrypt from "bcrypt"; +import { UserRepository } from "../repositories/userRepository"; +import { generateTokens } from "../lib/token"; + +export class UserService { + private userRepo = new UserRepository(); + + async register(email: string, nickname: string, password: string) { + const exists = await this.userRepo.findByEmail(email); + if (exists) throw new Error("EMAIL_EXISTS"); + + const salt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(password, salt); + + await this.userRepo.createUser(email, nickname, hashedPassword); + return { message: "User registered successfully" }; + } + + async getProfile(userId: number) { + return this.userRepo.findById(userId); + } + + async updateInformation(userId: number, nickname?: string, image?: string) { + const updateData: Record = {}; + if (nickname) updateData.nickname = nickname; + if (image) updateData.image = image; + + if (Object.keys(updateData).length === 0) throw new Error("NO_DATA"); + + return this.userRepo.updateUser(userId, updateData); + } + + async updatePassword(userId: number, password: string) { + const salt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(password, salt); + await this.userRepo.updateUser(userId, { password: hashedPassword }); + return { message: "Password updated successfully" }; + } + + async getProducts(userId: number) { + return this.userRepo.findProductsByUserId(userId); + } + + generateUserTokens(userId: number) { + return generateTokens(userId); + } +} diff --git a/mission5_dtos/src/types/express.d.ts b/mission5_dtos/src/types/express.d.ts new file mode 100644 index 000000000..6f994ace7 --- /dev/null +++ b/mission5_dtos/src/types/express.d.ts @@ -0,0 +1,11 @@ +import type { User as PrismaUser } from "@prisma/client"; + +declare global { + namespace Express { + // Passport req.user 타입을 Prisma User로 확장 + interface User extends PrismaUser {} + } +} + +// 반드시 export {} 필요 +export {}; \ No newline at end of file diff --git a/mission5_dtos/tsconfig.json b/mission5_dtos/tsconfig.json new file mode 100644 index 000000000..e732234c0 --- /dev/null +++ b/mission5_dtos/tsconfig.json @@ -0,0 +1,48 @@ +{ + // Visit https://aka.ms/tsconfig to read more about this file + "compilerOptions": { + // File Layout + "rootDir": "./src", + "outDir": "./dist", + + // Environment Settings + // See also https://aka.ms/tsconfig/module + "module": "CommonJS", + "target": "ESNext", + // "types": [], + // For nodejs: + "lib": ["esnext"], + "types": ["node", "express", "passport"], + "allowJs": true, + "checkJs": true, + // and npm install -D @types/node + + // Other Outputs + "sourceMap": true, + "declaration": true, + "declarationMap": true, + + // Stricter Typechecking Options + "noUncheckedIndexedAccess": true, + "exactOptionalPropertyTypes": true, + + // Style Options + // "noImplicitReturns": true, + // "noImplicitOverride": true, + // "noUnusedLocals": true, + // "noUnusedParameters": true, + // "noFallthroughCasesInSwitch": true, + // "noPropertyAccessFromIndexSignature": true, + + // Recommended Options + "strict": true, + "jsx": "react-jsx", + "verbatimModuleSyntax": false, + "isolatedModules": true, + "noUncheckedSideEffectImports": true, + "moduleDetection": "force", + "skipLibCheck": true, + "esModuleInterop": true, + }, + "include": ["src/**/*", "src/types/**/*"] +} \ No newline at end of file From 4e70aeb14439335d390ab702fd1385977acf1233 Mon Sep 17 00:00:00 2001 From: Batur-s Date: Mon, 15 Sep 2025 17:24:10 +0900 Subject: [PATCH 26/38] Refactoring dto --- .../src/controllers/articleController.ts | 129 +++++++----------- .../src/controllers/productController.ts | 34 +---- .../src/controllers/userController.ts | 15 +- mission5_dtos/src/dtos/article.dto.ts | 38 ++++++ mission5_dtos/src/dtos/product.dto.ts | 28 ++++ mission5_dtos/src/dtos/user.dto.ts | 29 ++++ .../src/repositories/articleRepository.ts | 28 ++-- .../src/repositories/productRepository.ts | 1 + mission5_dtos/src/services/articleService.ts | 12 +- mission5_dtos/src/services/productService.ts | 5 +- mission5_dtos/src/services/userService.ts | 13 +- 11 files changed, 188 insertions(+), 144 deletions(-) create mode 100644 mission5_dtos/src/dtos/article.dto.ts create mode 100644 mission5_dtos/src/dtos/product.dto.ts create mode 100644 mission5_dtos/src/dtos/user.dto.ts diff --git a/mission5_dtos/src/controllers/articleController.ts b/mission5_dtos/src/controllers/articleController.ts index 0f7fa60a8..250dac6e8 100644 --- a/mission5_dtos/src/controllers/articleController.ts +++ b/mission5_dtos/src/controllers/articleController.ts @@ -1,102 +1,71 @@ import { Request, Response, NextFunction } from "express"; -import { z } from "zod"; import status from "http-status"; import { ArticleService } from "../services/articleService"; +import { ArticleCreateSchema, ArticleUpdateSchema, ArticleQuerySchema, ArticleUpdateDTO } from "../dtos/article.dto"; const articleService = new ArticleService(); -// body 검증 (게시글 생성/수정) -const articleSchema = z.object({ - title: z.string().min(1, { message: "제목을 입력해주세요" }), - content: z - .string() - .min(10, { message: "내용은 최소 10자 이상이어야 합니다." }) - .max(200, { message: "내용은 최대 200자까지 가능합니다." }) -}); - -// PATCH용 스키마 (선택적) -const articleUpdateSchema = z.object({ - title: z.string().min(1, { message: "제목을 입력해주세요" }).optional(), - content: z - .string() - .min(10, { message: "내용은 최소 10자 이상이어야 합니다." }) - .max(200, { message: "내용은 최대 200자까지 가능합니다." }) - .optional(), -}); - -// query 검증 (게시글 조회) -const articleQuerySchema = z.object({ - page: z - .string() - .default("1") - .transform(Number) - .refine((val) => val > 0, { message: "page는 1 이상의 정수여야 합니다." }), - pageSize: z - .string() - .default("5") - .transform(Number) - .refine((val) => val > 0 && val <= 100, { - message: "pageSize는 1~100 사이여야 합니다.", - }), - keyword: z.string().default(""), -}); - export class ArticleController { - async create(req: Request, res: Response, next: NextFunction) { - try { - if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); - const parsed = articleSchema.parse(req.body); - const article = await articleService.create(req.user.id, parsed); - res.status(status.CREATED).json(article); - } catch (err) { - next(err); - } + async create(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const parsed = ArticleCreateSchema.parse(req.body); + const article = await articleService.create(req.user.id, parsed); + res.status(status.CREATED).json(article); + } catch (err) { + next(err); } + } - async list(req: Request, res: Response, next: NextFunction) { - try { - const { page, pageSize, keyword } = articleQuerySchema.parse(req.query); - const articles = await articleService.list(page, pageSize, keyword); - res.status(status.OK).json(articles); - } catch (err) { - next(err); - } + async list(req: Request, res: Response, next: NextFunction) { + try { + const parsed = ArticleQuerySchema.parse(req.query); + const articles = await articleService.list(parsed); + res.status(status.OK).json(articles); + } catch (err) { + next(err); } + } - async detail(req: Request, res: Response, next: NextFunction) { + async detail(req: Request, res: Response, next: NextFunction) { try { const articleId = Number(req.params.id); const article = await articleService.getDetail(articleId); - if (!article) return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + if (!article) return res.status(status.NOT_FOUND).json({ message: "Article not found" }); res.status(status.OK).json(article); } catch (err) { next(err); } } - async update(req: Request, res: Response, next: NextFunction) { - try { - if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); - const parsed = articleUpdateSchema.parse(req.body) as { title?: string; content?: string }; - const articleId = Number(req.params.id); - const updated = await articleService.update(req.user.id, articleId, parsed); - res.status(status.OK).json(updated); - } catch (err: any) { - if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" }); - if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); - next(err); - } + async update(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const parsed = ArticleUpdateSchema.parse(req.body) as { title?: string; content?: string; }; + const articleId = Number(req.params.id); + const updated = await articleService.update(req.user.id, articleId, parsed); + + res.status(status.OK).json(updated); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); } - async delete(req: Request, res: Response, next: NextFunction) { - try { - if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); - const articleId = Number(req.params.id); - await articleService.delete(req.user.id, articleId); - res.status(status.NO_CONTENT).end(); - } catch (err: any) { - if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" }); - if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); - next(err); - } + } + + async delete(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const articleId = Number(req.params.id); + await articleService.delete(req.user.id, articleId); + res.status(status.NO_CONTENT).end(); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); } -} \ No newline at end of file + } +} diff --git a/mission5_dtos/src/controllers/productController.ts b/mission5_dtos/src/controllers/productController.ts index 1f9a38e1b..5d42d09b9 100644 --- a/mission5_dtos/src/controllers/productController.ts +++ b/mission5_dtos/src/controllers/productController.ts @@ -1,38 +1,15 @@ import { Request, Response, NextFunction } from "express"; -import { z } from "zod"; import status from "http-status"; import { ProductService } from "../services/productService"; +import { ProductCreateSchema, ProductUpdateSchema, ProductQuerySchema } from "../dtos/product.dto"; const productService = new ProductService(); -// body 검증(생성) -const productSchema = z.object({ - name: z.string().min(1, { message: "이름을 입력해주세요" }), - description: z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }), - price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }), - tags: z.string().default(""), -}); - -// body 검증(수정) -const productUpdateSchema = z.object({ - name: z.string().min(1, { message: "이름을 입력해주세요" }).optional(), - description: z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }).optional(), - price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }).optional(), - tags: z.string().default("").optional(), -}); - -// query 검증 -const productQuerySchema = z.object({ - page: z.string().default("1").transform(Number).refine((v) => v > 0), - pageSize: z.string().default("5").transform(Number).refine((v) => v > 0 && v <= 100), - keyword: z.string().default(""), -}); - export class ProductController { async create(req: Request, res: Response, next: NextFunction) { try { if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); - const parsed = productSchema.parse(req.body); + const parsed = ProductCreateSchema.parse(req.body); const product = await productService.create(req.user.id, parsed); res.status(status.CREATED).json(product); } catch (err) { @@ -42,8 +19,8 @@ export class ProductController { async list(req: Request, res: Response, next: NextFunction) { try { - const { page, pageSize, keyword } = productQuerySchema.parse(req.query); - const products = await productService.list(page, pageSize, keyword); + const parsed = ProductQuerySchema.parse(req.query); + const products = await productService.list(parsed); res.status(status.OK).json(products); } catch (err) { next(err); @@ -64,9 +41,10 @@ export class ProductController { async update(req: Request, res: Response, next: NextFunction) { try { if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); - const parsed = productUpdateSchema.parse(req.body) as { name?: string; description?: string; price?: number; tags?: string; }; + const parsed = ProductUpdateSchema.parse(req.body) as { name?: string; description?: string; price?: number; tags?: string; }; const productId = Number(req.params.id); const updated = await productService.update(req.user.id, productId, parsed); + res.status(status.OK).json(updated); } catch (err: any) { if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" }); diff --git a/mission5_dtos/src/controllers/userController.ts b/mission5_dtos/src/controllers/userController.ts index d73a5ee30..8f706c6b5 100644 --- a/mission5_dtos/src/controllers/userController.ts +++ b/mission5_dtos/src/controllers/userController.ts @@ -2,14 +2,15 @@ import { Request, Response, NextFunction } from "express"; import status from "http-status"; import { UserService } from "../services/userService"; import { setTokenCookies, clearTokenCookies } from "../lib/cookieUtil"; +import { UserRegisterSchema, UserUpdateSchema, UserPasswordSchema, UserLoginSchema } from "../dtos/user.dto"; const userService = new UserService(); export class UserController { async register(req: Request, res: Response, next: NextFunction) { - const { email, nickname, password } = req.body; try { - const result = await userService.register(email, nickname, password); + const parsed = UserRegisterSchema.parse(req.body); + const result = await userService.register(parsed); res.status(status.CREATED).json(result); } catch (err: any) { if (err.message === "EMAIL_EXISTS") { @@ -44,7 +45,10 @@ export class UserController { async modifyInformation(req: Request, res: Response, next: NextFunction) { try { if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); - const updatedUser = await userService.updateInformation(req.user.id, req.body.nickname, req.body.image); + + const parsed = UserUpdateSchema.parse(req.body); // DTO 검증 + const updatedUser = await userService.updateInformation(req.user.id, parsed.nickname, parsed.image); + res.status(status.OK).json({ message: "User information updated successfully", user: updatedUser }); } catch (err: any) { if (err.message === "NO_DATA") return res.status(status.BAD_REQUEST).json({ message: "No update data provided" }); @@ -55,7 +59,10 @@ export class UserController { async modifyPassword(req: Request, res: Response, next: NextFunction) { try { if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); - const result = await userService.updatePassword(req.user.id, req.body.password); + + const parsed = UserPasswordSchema.parse(req.body); // DTO 검증 + const result = await userService.updatePassword(req.user.id, parsed); + res.status(status.OK).json(result); } catch (err) { next(err); diff --git a/mission5_dtos/src/dtos/article.dto.ts b/mission5_dtos/src/dtos/article.dto.ts new file mode 100644 index 000000000..c6709cf00 --- /dev/null +++ b/mission5_dtos/src/dtos/article.dto.ts @@ -0,0 +1,38 @@ +import { z } from "zod"; + +// CREATE DTO +export const ArticleCreateSchema = z.object({ + title: z.string().min(1, { message: "제목을 입력해주세요" }), + content: z + .string() + .min(10, { message: "내용은 최소 10자 이상이어야 합니다." }) + .max(200, { message: "내용은 최대 200자까지 가능합니다." }), +}); +export type ArticleCreateDTO = z.infer; + +// UPDATE DTO (PATCH) +export const ArticleUpdateSchema = z.object({ + title: z.string().min(1, { message: "제목을 입력해주세요" }).optional(), + content: z + .string() + .min(10, { message: "내용은 최소 10자 이상이어야 합니다." }) + .max(200, { message: "내용은 최대 200자까지 가능합니다." }) + .optional(), +}); +export type ArticleUpdateDTO = z.infer; + +// QUERY DTO (GET /articles) +export const ArticleQuerySchema = z.object({ + page: z + .string() + .default("1") + .transform(Number) + .refine((val) => val > 0, { message: "page는 1 이상의 정수여야 합니다." }), + pageSize: z + .string() + .default("5") + .transform(Number) + .refine((val) => val > 0 && val <= 100, { message: "pageSize는 1~100 사이여야 합니다." }), + keyword: z.string().default(""), +}); +export type ArticleQueryDTO = z.infer; diff --git a/mission5_dtos/src/dtos/product.dto.ts b/mission5_dtos/src/dtos/product.dto.ts new file mode 100644 index 000000000..edac3858a --- /dev/null +++ b/mission5_dtos/src/dtos/product.dto.ts @@ -0,0 +1,28 @@ +import { z } from "zod"; + + +// CREATE DTO +export const ProductCreateSchema = z.object({ + name: z.string().min(1, { message: "이름을 입력해주세요" }), + description: z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }), + price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }), + tags: z.string().default(""), +}); +export type ProductCreateDTO = z.infer; + +// UPDATE DTO +export const ProductUpdateSchema = z.object({ + name: z.string().min(1, { message: "이름을 입력해주세요" }).optional(), + description: z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }).optional(), + price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }).optional(), + tags: z.string().default("").optional(), +}); +export type ProductUpdateDTO = z.infer; + +// QUERY DTO +export const ProductQuerySchema = z.object({ + page: z.string().default("1").transform(Number).refine((v) => v > 0), + pageSize: z.string().default("5").transform(Number).refine((v) => v > 0 && v <= 100), + keyword: z.string().default(""), +}); +export type ProductQueryDTO = z.infer; \ No newline at end of file diff --git a/mission5_dtos/src/dtos/user.dto.ts b/mission5_dtos/src/dtos/user.dto.ts new file mode 100644 index 000000000..1bed9d74a --- /dev/null +++ b/mission5_dtos/src/dtos/user.dto.ts @@ -0,0 +1,29 @@ +import { z } from "zod"; + +// 회원가입 +export const UserRegisterSchema = z.object({ + email: z.string().email({ message: "Invalid email" }), + nickname: z.string().min(2, { message: "Nickname too short" }), + password: z.string().min(6, { message: "Password too short" }), +}); +export type UserRegisterDTO = z.infer; + +// 로그인 +export const UserLoginSchema = z.object({ + email: z.string().email(), + password: z.string().min(6), +}); +export type UserLoginDTO = z.infer; + +// 정보 수정 (PATCH) +export const UserUpdateSchema = z.object({ + nickname: z.string().min(2).optional(), + image: z.string().url().optional(), +}); +export type UserUpdateDTO = z.infer; + +// 비밀번호 수정 +export const UserPasswordSchema = z.object({ + password: z.string().min(6, { message: "Password too short" }), +}); +export type UserPasswordDTO = z.infer; diff --git a/mission5_dtos/src/repositories/articleRepository.ts b/mission5_dtos/src/repositories/articleRepository.ts index 12e328cbc..07318b163 100644 --- a/mission5_dtos/src/repositories/articleRepository.ts +++ b/mission5_dtos/src/repositories/articleRepository.ts @@ -2,7 +2,7 @@ import prisma from "../lib/prisma"; import { Prisma } from "@prisma/client"; export class ArticleRepository { - async createArticle(data: { userId: number, title: string, content: string }) { + async createArticle(data: { userId: number; title: string; content: string }) { return prisma.article.create({ data }); } @@ -11,12 +11,7 @@ export class ArticleRepository { skip, take, orderBy: { createdAt: "desc" }, - select: { - id: true, - title: true, - content: true, - createdAt: true, - }, + select: { id: true, title: true, content: true, createdAt: true }, where, }); } @@ -24,21 +19,20 @@ export class ArticleRepository { async findById(id: number) { return prisma.article.findUnique({ where: { id }, - select: { - id: true, - userId: true, - title: true, - content: true, - createdAt: true, - }, + select: { id: true, userId: true, title: true, content: true, createdAt: true }, }); } - async updatedArticle(id: number, data: Partial<{ title: string, content: string }>) { - return prisma.article.update({ where: { id }, data }); + async updatedArticle(id: number, data: { title?: string; content?: string }) { + // undefined 필드 제거 + const updateData: { title?: string; content?: string } = {}; + if (data.title !== undefined) updateData.title = data.title; + if (data.content !== undefined) updateData.content = data.content; + + return prisma.article.update({ where: { id }, data: updateData }); } async deleteArticle(id: number) { return prisma.article.delete({ where: { id } }); } -} \ No newline at end of file +} diff --git a/mission5_dtos/src/repositories/productRepository.ts b/mission5_dtos/src/repositories/productRepository.ts index 21f7475ca..62b287709 100644 --- a/mission5_dtos/src/repositories/productRepository.ts +++ b/mission5_dtos/src/repositories/productRepository.ts @@ -1,5 +1,6 @@ import prisma from "../lib/prisma"; import { Prisma } from "@prisma/client"; +import { ProductCreateDTO, ProductUpdateDTO, ProductQueryDTO } from "../dtos/product.dto"; export class ProductRepository { async createProduct(data: { userId: number; name: string; description: string; price: number; tags: string }) { diff --git a/mission5_dtos/src/services/articleService.ts b/mission5_dtos/src/services/articleService.ts index 8df8210d4..276bad3df 100644 --- a/mission5_dtos/src/services/articleService.ts +++ b/mission5_dtos/src/services/articleService.ts @@ -1,14 +1,15 @@ import { ArticleRepository } from "../repositories/articleRepository"; +import type { ArticleCreateDTO, ArticleUpdateDTO, ArticleQueryDTO } from "../dtos/article.dto"; import type { Prisma } from "@prisma/client"; export class ArticleService { private repo = new ArticleRepository(); - async create(userId: number, data: { title: string; content: string }) { + async create(userId: number, data: ArticleCreateDTO) { return this.repo.createArticle({ ...data, userId }); } - async list(page: number, pageSize: number, keyword: string) { + async list({ page, pageSize, keyword }: ArticleQueryDTO) { const where: Prisma.ArticleWhereInput = keyword ? { OR: [ @@ -17,6 +18,7 @@ export class ArticleService { ], } : {}; + return this.repo.findMany(where, (page - 1) * pageSize, pageSize); } @@ -24,11 +26,7 @@ export class ArticleService { return this.repo.findById(id); } - async update( - userId: number, - articleId: number, - data: { title?: string; content?: string; } - ) { + async update(userId: number, articleId: number, data: { title?: string; content?: string; }) { const article = await this.repo.findById(articleId); if (!article) throw new Error("NOT_FOUND"); if (article.userId !== userId) throw new Error("FORBIDDEN"); diff --git a/mission5_dtos/src/services/productService.ts b/mission5_dtos/src/services/productService.ts index 62780c6b3..32933402e 100644 --- a/mission5_dtos/src/services/productService.ts +++ b/mission5_dtos/src/services/productService.ts @@ -1,14 +1,15 @@ import { ProductRepository } from "../repositories/productRepository"; +import type { ProductCreateDTO, ProductUpdateDTO, ProductQueryDTO } from "../dtos/product.dto"; import type { Prisma } from "@prisma/client"; export class ProductService { private repo = new ProductRepository(); - async create(userId: number, data: { name: string; description: string; price: number; tags: string }) { + async create(userId: number, data: ProductCreateDTO) { return this.repo.createProduct({ ...data, userId }); } - async list(page: number, pageSize: number, keyword: string) { + async list({ page, pageSize, keyword }: ProductQueryDTO) { const where: Prisma.ProductWhereInput = keyword ? { OR: [ diff --git a/mission5_dtos/src/services/userService.ts b/mission5_dtos/src/services/userService.ts index 5294115cb..f9bd91fc2 100644 --- a/mission5_dtos/src/services/userService.ts +++ b/mission5_dtos/src/services/userService.ts @@ -1,18 +1,19 @@ import bcrypt from "bcrypt"; import { UserRepository } from "../repositories/userRepository"; import { generateTokens } from "../lib/token"; +import type { UserRegisterDTO, UserUpdateDTO, UserPasswordDTO } from "../dtos/user.dto"; export class UserService { private userRepo = new UserRepository(); - async register(email: string, nickname: string, password: string) { - const exists = await this.userRepo.findByEmail(email); + async register(data: UserRegisterDTO) { + const exists = await this.userRepo.findByEmail(data.email); if (exists) throw new Error("EMAIL_EXISTS"); const salt = await bcrypt.genSalt(10); - const hashedPassword = await bcrypt.hash(password, salt); + const hashedPassword = await bcrypt.hash(data.password, salt); - await this.userRepo.createUser(email, nickname, hashedPassword); + await this.userRepo.createUser(data.email, data.nickname, hashedPassword); return { message: "User registered successfully" }; } @@ -30,9 +31,9 @@ export class UserService { return this.userRepo.updateUser(userId, updateData); } - async updatePassword(userId: number, password: string) { + async updatePassword(userId: number, data: UserPasswordDTO) { const salt = await bcrypt.genSalt(10); - const hashedPassword = await bcrypt.hash(password, salt); + const hashedPassword = await bcrypt.hash(data.password, salt); await this.userRepo.updateUser(userId, { password: hashedPassword }); return { message: "Password updated successfully" }; } From 23d1256b638cd52b6e8c9980dcfd9a9b23a1c953 Mon Sep 17 00:00:00 2001 From: Batur-s Date: Tue, 16 Sep 2025 17:32:03 +0900 Subject: [PATCH 27/38] =?UTF-8?q?Refactoring:=20=ED=8C=8C=EC=B8=A0?= =?UTF-8?q?=EB=A5=BC=20=EA=B0=81=EA=B0=81=20=EB=B6=84=EB=A6=AC=20=ED=9B=84?= =?UTF-8?q?=20dto=EB=A5=BC=20=ED=86=B5=ED=95=9C=20module=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mission5/src/app.ts | 10 +- .../src/controllers/articleController.ts | 0 .../src/controllers/commentController.ts | 0 .../src/controllers/likeController.ts | 0 .../src/controllers/photoController.ts | 0 .../src/controllers/productController.ts | 0 .../src/controllers/userController.ts | 0 .../src/dtos/article.dto.ts | 0 .../src/dtos/product.dto.ts | 0 .../src/dtos/user.dto.ts | 0 .../src/lib/cookieUtil.ts | 0 .../src/repositories/articleRepository.ts | 0 .../src/repositories/commentRepository.ts | 0 .../src/repositories/likeRepository.ts | 0 .../src/repositories/productRepository.ts | 0 .../src/repositories/userRepository.ts | 0 mission5/src/routers/articleRouter.ts | 209 +- mission5/src/routers/commentRouter.ts | 237 +- mission5/src/routers/index.ts | 27 +- mission5/src/routers/likeRouter.ts | 213 +- mission5/src/routers/photoRouter.ts | 33 +- mission5/src/routers/productRouter.ts | 226 +- mission5/src/routers/userRouter.ts | 240 +- .../src/services/articleService.ts | 0 .../src/services/commentService.ts | 0 .../src/services/likeService.ts | 0 .../src/services/productService.ts | 0 .../src/services/userService.ts | 0 mission5/src/types/express.d.ts | 2 +- mission5_dtos/.gitignore | 5 - mission5_dtos/package-lock.json | 3128 ----------------- mission5_dtos/package.json | 49 - .../20250904083711_test/migration.sql | 94 - .../prisma/migrations/migration_lock.toml | 3 - mission5_dtos/prisma/schema.prisma | 75 - mission5_dtos/src/app.ts | 31 - mission5_dtos/src/lib/constants.ts | 21 - mission5_dtos/src/lib/passport/index.ts | 9 - mission5_dtos/src/lib/passport/jwtStrategy.ts | 45 - .../src/lib/passport/localStrategy.ts | 27 - mission5_dtos/src/lib/prisma.ts | 5 - mission5_dtos/src/lib/token.ts | 27 - mission5_dtos/src/middlewares/errorHandler.ts | 22 - mission5_dtos/src/routers/articleRouter.ts | 14 - mission5_dtos/src/routers/commentRouter.ts | 15 - mission5_dtos/src/routers/index.ts | 19 - mission5_dtos/src/routers/likeRouter.ts | 13 - mission5_dtos/src/routers/photoRouter.ts | 18 - mission5_dtos/src/routers/productRouter.ts | 14 - mission5_dtos/src/routers/userRouter.ts | 17 - mission5_dtos/src/types/express.d.ts | 11 - mission5_dtos/tsconfig.json | 48 - 52 files changed, 81 insertions(+), 4826 deletions(-) rename {mission5_dtos => mission5}/src/controllers/articleController.ts (100%) rename {mission5_dtos => mission5}/src/controllers/commentController.ts (100%) rename {mission5_dtos => mission5}/src/controllers/likeController.ts (100%) rename {mission5_dtos => mission5}/src/controllers/photoController.ts (100%) rename {mission5_dtos => mission5}/src/controllers/productController.ts (100%) rename {mission5_dtos => mission5}/src/controllers/userController.ts (100%) rename {mission5_dtos => mission5}/src/dtos/article.dto.ts (100%) rename {mission5_dtos => mission5}/src/dtos/product.dto.ts (100%) rename {mission5_dtos => mission5}/src/dtos/user.dto.ts (100%) rename {mission5_dtos => mission5}/src/lib/cookieUtil.ts (100%) rename {mission5_dtos => mission5}/src/repositories/articleRepository.ts (100%) rename {mission5_dtos => mission5}/src/repositories/commentRepository.ts (100%) rename {mission5_dtos => mission5}/src/repositories/likeRepository.ts (100%) rename {mission5_dtos => mission5}/src/repositories/productRepository.ts (100%) rename {mission5_dtos => mission5}/src/repositories/userRepository.ts (100%) rename {mission5_dtos => mission5}/src/services/articleService.ts (100%) rename {mission5_dtos => mission5}/src/services/commentService.ts (100%) rename {mission5_dtos => mission5}/src/services/likeService.ts (100%) rename {mission5_dtos => mission5}/src/services/productService.ts (100%) rename {mission5_dtos => mission5}/src/services/userService.ts (100%) delete mode 100644 mission5_dtos/.gitignore delete mode 100644 mission5_dtos/package-lock.json delete mode 100644 mission5_dtos/package.json delete mode 100644 mission5_dtos/prisma/migrations/20250904083711_test/migration.sql delete mode 100644 mission5_dtos/prisma/migrations/migration_lock.toml delete mode 100644 mission5_dtos/prisma/schema.prisma delete mode 100644 mission5_dtos/src/app.ts delete mode 100644 mission5_dtos/src/lib/constants.ts delete mode 100644 mission5_dtos/src/lib/passport/index.ts delete mode 100644 mission5_dtos/src/lib/passport/jwtStrategy.ts delete mode 100644 mission5_dtos/src/lib/passport/localStrategy.ts delete mode 100644 mission5_dtos/src/lib/prisma.ts delete mode 100644 mission5_dtos/src/lib/token.ts delete mode 100644 mission5_dtos/src/middlewares/errorHandler.ts delete mode 100644 mission5_dtos/src/routers/articleRouter.ts delete mode 100644 mission5_dtos/src/routers/commentRouter.ts delete mode 100644 mission5_dtos/src/routers/index.ts delete mode 100644 mission5_dtos/src/routers/likeRouter.ts delete mode 100644 mission5_dtos/src/routers/photoRouter.ts delete mode 100644 mission5_dtos/src/routers/productRouter.ts delete mode 100644 mission5_dtos/src/routers/userRouter.ts delete mode 100644 mission5_dtos/src/types/express.d.ts delete mode 100644 mission5_dtos/tsconfig.json diff --git a/mission5/src/app.ts b/mission5/src/app.ts index 2cedd491e..9be0a16ce 100644 --- a/mission5/src/app.ts +++ b/mission5/src/app.ts @@ -10,12 +10,8 @@ const app = express(); app.use(express.urlencoded({ extended: true })); -app.use(cookieParser()); app.use(express.json()); -app.use(passport.initialize()); -app.use(router); -app.use("/download", express.static("uploads")); - +app.use(cookieParser()); const corsOptions = { //CORS 설정 및 whitelist로 'http://localhost:3000'을 설정 origin: "http://localhost:3000", @@ -23,6 +19,10 @@ const corsOptions = { }; app.use(cors(corsOptions)); +app.use(passport.initialize()); +app.use(router); +app.use("/download", express.static("uploads")); + app.use(errorHandler); diff --git a/mission5_dtos/src/controllers/articleController.ts b/mission5/src/controllers/articleController.ts similarity index 100% rename from mission5_dtos/src/controllers/articleController.ts rename to mission5/src/controllers/articleController.ts diff --git a/mission5_dtos/src/controllers/commentController.ts b/mission5/src/controllers/commentController.ts similarity index 100% rename from mission5_dtos/src/controllers/commentController.ts rename to mission5/src/controllers/commentController.ts diff --git a/mission5_dtos/src/controllers/likeController.ts b/mission5/src/controllers/likeController.ts similarity index 100% rename from mission5_dtos/src/controllers/likeController.ts rename to mission5/src/controllers/likeController.ts diff --git a/mission5_dtos/src/controllers/photoController.ts b/mission5/src/controllers/photoController.ts similarity index 100% rename from mission5_dtos/src/controllers/photoController.ts rename to mission5/src/controllers/photoController.ts diff --git a/mission5_dtos/src/controllers/productController.ts b/mission5/src/controllers/productController.ts similarity index 100% rename from mission5_dtos/src/controllers/productController.ts rename to mission5/src/controllers/productController.ts diff --git a/mission5_dtos/src/controllers/userController.ts b/mission5/src/controllers/userController.ts similarity index 100% rename from mission5_dtos/src/controllers/userController.ts rename to mission5/src/controllers/userController.ts diff --git a/mission5_dtos/src/dtos/article.dto.ts b/mission5/src/dtos/article.dto.ts similarity index 100% rename from mission5_dtos/src/dtos/article.dto.ts rename to mission5/src/dtos/article.dto.ts diff --git a/mission5_dtos/src/dtos/product.dto.ts b/mission5/src/dtos/product.dto.ts similarity index 100% rename from mission5_dtos/src/dtos/product.dto.ts rename to mission5/src/dtos/product.dto.ts diff --git a/mission5_dtos/src/dtos/user.dto.ts b/mission5/src/dtos/user.dto.ts similarity index 100% rename from mission5_dtos/src/dtos/user.dto.ts rename to mission5/src/dtos/user.dto.ts diff --git a/mission5_dtos/src/lib/cookieUtil.ts b/mission5/src/lib/cookieUtil.ts similarity index 100% rename from mission5_dtos/src/lib/cookieUtil.ts rename to mission5/src/lib/cookieUtil.ts diff --git a/mission5_dtos/src/repositories/articleRepository.ts b/mission5/src/repositories/articleRepository.ts similarity index 100% rename from mission5_dtos/src/repositories/articleRepository.ts rename to mission5/src/repositories/articleRepository.ts diff --git a/mission5_dtos/src/repositories/commentRepository.ts b/mission5/src/repositories/commentRepository.ts similarity index 100% rename from mission5_dtos/src/repositories/commentRepository.ts rename to mission5/src/repositories/commentRepository.ts diff --git a/mission5_dtos/src/repositories/likeRepository.ts b/mission5/src/repositories/likeRepository.ts similarity index 100% rename from mission5_dtos/src/repositories/likeRepository.ts rename to mission5/src/repositories/likeRepository.ts diff --git a/mission5_dtos/src/repositories/productRepository.ts b/mission5/src/repositories/productRepository.ts similarity index 100% rename from mission5_dtos/src/repositories/productRepository.ts rename to mission5/src/repositories/productRepository.ts diff --git a/mission5_dtos/src/repositories/userRepository.ts b/mission5/src/repositories/userRepository.ts similarity index 100% rename from mission5_dtos/src/repositories/userRepository.ts rename to mission5/src/repositories/userRepository.ts diff --git a/mission5/src/routers/articleRouter.ts b/mission5/src/routers/articleRouter.ts index 0ad073b08..4c4161a6b 100644 --- a/mission5/src/routers/articleRouter.ts +++ b/mission5/src/routers/articleRouter.ts @@ -1,203 +1,14 @@ -import express, { type Request, type Response, type NextFunction } from "express"; -import prisma from "../lib/prisma"; -import passport from "../lib/passport/index"; -import { z } from "zod"; -import status from "http-status"; -import type { Prisma } from "@prisma/client"; +import express from "express"; +import passport from "../lib/passport"; +import { ArticleController } from "../controllers/articleController"; const router = express.Router(); +const controller = new ArticleController(); -// body 검증 (게시글 생성/수정) -const articleSchema = z.object({ - title: z.string().min(1, { message: "제목을 입력해주세요" }), - content: z - .string() - .min(10, { message: "내용은 최소 10자 이상이어야 합니다." }) - .max(200, { message: "내용은 최대 200자까지 가능합니다." }) -}); +router.post("/", passport.authenticate("access-token", { session: false }), controller.create); +router.get("/", passport.authenticate("access-token", { session: false }), controller.list); +router.get("/:id", passport.authenticate("access-token", { session: false }), controller.detail); +router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update); +router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete); -// query 검증 (게시글 조회) -const articleQuerySchema = z.object({ - page: z - .string() - .default("1") - .transform(Number) - .refine((val) => val > 0, { message: "page는 1 이상의 정수여야 합니다." }), - pageSize: z - .string() - .default("5") - .transform(Number) - .refine((val) => val > 0 && val <= 100, { - message: "pageSize는 1~100 사이여야 합니다.", - }), - keyword: z.string().default(""), -}); - -router.post( - "/articles", - passport.authenticate("access-token", { session: false }), - createArticle -); -router.get("/articles", getArticles); -router.patch( - "/articles/:id", - passport.authenticate("access-token", { session: false }), - modifyArticle -); -router.delete( - "/articles/:id", - passport.authenticate("access-token", { session: false }), - deleteArticle -); -router.get( - "/articles/:id", - passport.authenticate("access-token", { session: false }), - getDetailArticle -); - -async function createArticle(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - const user = req.user; - const parsed = articleSchema.parse(req.body); - - try { - const article = await prisma.article.create({ - data: { - ...parsed, - userId: user.id, - }, - }); - - res.status(status.CREATED).json(article); - } catch (err) { - next(err); - } -} - -async function getArticles(req: Request, res: Response, next: NextFunction) { - const { page, pageSize, keyword } = articleQuerySchema.parse(req.query); - const where: Prisma.ArticleWhereInput = keyword //title과 content 에서 원하는 keyword가 있는 데이터를 찾도록 만든 변수 - ? { - OR: [ - { - title: { - contains: keyword, - mode: "insensitive", //대소문자 구분 없이 검색하기 위해 - }, - }, - { - content: { - contains: keyword, - mode: "insensitive", - }, - }, - ], - } - : {}; //기본값 {}으로 빈 객체를 수식하기 위함 - - try { - const articles = await prisma.article.findMany({ - skip: (page - 1) * pageSize, //offset pagination - take: pageSize, - orderBy: { - // 최신 순서대로 정렬하기(최신순) - createdAt: "desc", - }, - select: { - id: true, - title: true, - content: true, - createdAt: true, - }, - where, - }); - - res.status(status.OK).json(articles); - } catch (err) { - next(err); - } -} - -async function modifyArticle(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - const articleId = Number(req.params.id); - const parsed = articleSchema.parse(req.body); - const user = req.user; - - try { - const article = await prisma.article.findUnique({ - where: { id: articleId }, - }); - - if (!article) { - return res - .status(status.NOT_FOUND) - .json({ message: "Article not found" }); - } - if (article.userId !== user.id) { - return res.status(status.FORBIDDEN).json({ message: "User not matched" }); - } - - const updated = await prisma.article.update({ - where: { id: articleId }, - data: { - ...parsed, - }, - }); - res.status(status.OK).json(updated); - } catch (err) { - next(err); - } -} - -async function deleteArticle(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - const articleId = Number(req.params.id); - const user = req.user; - - try { - const article = await prisma.article.findUnique({ - where: { id: articleId }, - }); - - if (!article) { - return res - .status(status.NOT_FOUND) - .json({ message: "Article not found" }); - } - if (article.userId !== user.id) { - return res.status(status.FORBIDDEN).json({ message: "User not matched" }); - } - - await prisma.article.delete({ - where: { id: articleId }, - }); - res.status(status.NO_CONTENT).end(); - } catch (err) { - next(err); - } -} - -async function getDetailArticle(req: Request, res: Response, next: NextFunction) { - const articleId = Number(req.params.id); - - try { - const article = await prisma.article.findUnique({ - where: { id: articleId }, - select: { - id: true, - title: true, - content: true, - createdAt: true, - }, - }); - if (!article) { - return res.status(status.NOT_FOUND).json({ error: "Article not found" }); - } - res.status(status.OK).json(article); - } catch (err) { - next(err); - } -} - -export default router; +export default router; \ No newline at end of file diff --git a/mission5/src/routers/commentRouter.ts b/mission5/src/routers/commentRouter.ts index 28f9e0fc8..f7b6b4903 100644 --- a/mission5/src/routers/commentRouter.ts +++ b/mission5/src/routers/commentRouter.ts @@ -1,230 +1,15 @@ -import express, { type Request, type Response, type NextFunction } from "express"; -import prisma from "../lib/prisma"; -import passport from "../lib/passport/index"; -import { z } from "zod"; -import status from "http-status"; +import express from "express"; +import passport from "../lib/passport"; +import { CommentController } from "../controllers/commentController"; const router = express.Router(); +const controller = new CommentController(); -// body 검증 (댓글 생성/수정) -const commentSchema = z.object({ - content: z - .string() - .min(5, { message: "덧글은 최소 5자 이상이어야 합니다." }) - .max(100, { message: "덧글은 최대 100자까지 가능합니다." }), -}); +router.post("/products/:id", passport.authenticate("access-token", { session: false }), controller.createProductComment); +router.post("/articles/:id", passport.authenticate("access-token", { session: false }), controller.createArticleComment); +router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.modifyComment); +router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.deleteComment); +router.get("/products/:id", passport.authenticate("access-token", { session: false }), controller.productCommentList); +router.get("/articles/:id", passport.authenticate("access-token", { session: false }), controller.articleCommentList); -const commentListSchema = z.object({ - id: z.coerce - .number() - .int() - .positive({ message: "id는 양의 정수여야 합니다." }), - lastId: z.coerce.number().int().positive().optional(), -}); - -router.post( - "/comments/products/:id", - passport.authenticate("access-token", { session: false }), - createProductComment -); -router.post( - "/comments/articles/:id", - passport.authenticate("access-token", { session: false }), - createArticleComment -); -router.patch( - "/comments/:id", - passport.authenticate("access-token", { session: false }), - modifyComment -); -router.delete( - "/comments/:id", - passport.authenticate("access-token", { session: false }), - deleteComment -); -router.get( - "/comments/products/:id", - passport.authenticate("access-token", { session: false }), - productCommentList -); -router.get( - "/comments/articles/:id", - passport.authenticate("access-token", { session: false }), - articleCommentList -); - -async function createProductComment(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - const productId = Number(req.params.id); - const parsed = commentSchema.parse(req.body); - const user = req.user; - - try { - const comment = await prisma.comment.create({ - data: { - ...parsed, - productId, - articleId: null, - userId: user.id, - }, - }); - - res.status(status.CREATED).json(comment); - } catch (err) { - next(err); - } -} - -async function createArticleComment(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - const articleId = Number(req.params.id); - const parsed = commentSchema.parse(req.body); - const user = req.user; - - try { - const comment = await prisma.comment.create({ - data: { - ...parsed, - productId: null, - articleId, - userId: user.id, - }, - }); - - res.status(status.CREATED).json(comment); - } catch (err) { - next(err); - } -} - -async function modifyComment(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - const commentId = Number(req.params.id); - const parsed = commentSchema.parse(req.body); - const user = req.user; - - try { - const comment = await prisma.comment.findUnique({ - where: { id: commentId }, - }); - - if (!comment) { - return res - .status(status.NOT_FOUND) - .json({ message: "Comment not found" }); - } - if (comment.userId !== user.id) { - return res.status(status.FORBIDDEN).json({ message: "User not matched" }); - } - - const updated = await prisma.comment.update({ - where: { id: commentId }, - data: { - ...parsed, - }, - }); - res.status(status.OK).json(updated); - } catch (err) { - next(err); - } -} - -async function deleteComment(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - const commentId = Number(req.params.id); - const user = req.user; - - try { - const comment = await prisma.comment.findUnique({ - where: { id: commentId }, - }); - - if (!comment) { - return res - .status(status.NOT_FOUND) - .json({ message: "Comment not found" }); - } - if (comment.userId !== user.id) { - return res.status(status.FORBIDDEN).json({ message: "User not matched" }); - } - await prisma.comment.delete({ - where: { id: commentId }, - }); - - res.status(status.NO_CONTENT).end(); - } catch (err) { - next(err); - } -} - -async function productCommentList(req: Request, res: Response, next: NextFunction) { - try { - const parsed = commentListSchema.parse({ - id: req.params.id, - lastId: req.query.lastId, - }); - const { id: productId, lastId } = parsed; - - const comments = await prisma.comment.findMany({ - where: { - AND: [ - { - articleId: null, - }, - { - productId, - }, - ], - }, - take: 5, - skip: lastId ? 1 : 0, - ...(lastId && { cursor: { id: lastId } }), - select: { - id: true, - content: true, - createdAt: true, - }, - }); - - res.status(status.OK).json(comments); - } catch (err) { - next(err); - } -} - -async function articleCommentList(req: Request, res: Response, next: NextFunction) { - try { - const parsed = commentListSchema.parse({ - id: req.params.id, - lastId: req.query.lastId, - }); - const { id: articleId, lastId } = parsed; - - const comments = await prisma.comment.findMany({ - where: { - AND: [ - { - articleId, - }, - { - productId: null, - }, - ], - }, - take: 5, - skip: lastId ? 1 : 0, - ...(lastId && { cursor: { id: lastId } }), - select: { - id: true, - content: true, - createdAt: true, - }, - }); - - res.status(status.OK).json(comments); - } catch (err) { - next(err); - } -} - -export default router; +export default router; \ No newline at end of file diff --git a/mission5/src/routers/index.ts b/mission5/src/routers/index.ts index 589b90746..c1bafd4f0 100644 --- a/mission5/src/routers/index.ts +++ b/mission5/src/routers/index.ts @@ -1,18 +1,19 @@ -import express from 'express'; -import userRouter from './userRouter'; -import articleRouter from './articleRouter'; -import productRouter from './productRouter'; -import commentRouter from './commentRouter'; -import likeRouter from './likeRouter'; -import photoRouter from './photoRouter'; +import express from "express"; + +import userRouter from "./userRouter"; +import articleRouter from "./articleRouter"; +import productRouter from "./productRouter"; +import commentRouter from "./commentRouter"; +import likeRouter from "./likeRouter"; +import photoRouter from "./photoRouter"; // ✅ 공통 업로드 전용 const router = express.Router(); -router.use(userRouter); -router.use(articleRouter); -router.use(productRouter); -router.use(commentRouter); -router.use(likeRouter); -router.use(photoRouter); +router.use("/users", userRouter); +router.use("/articles", articleRouter); +router.use("/products", productRouter); +router.use("/comments", commentRouter); +router.use("/likes", likeRouter); +router.use(photoRouter); // 📌 prefix는 /photos export default router; \ No newline at end of file diff --git a/mission5/src/routers/likeRouter.ts b/mission5/src/routers/likeRouter.ts index d4f912d20..10ec9924d 100644 --- a/mission5/src/routers/likeRouter.ts +++ b/mission5/src/routers/likeRouter.ts @@ -1,208 +1,13 @@ -import express, { type Request, type Response, type NextFunction } from "express"; -import prisma from "../lib/prisma"; -import passport from "../lib/passport/index"; -import status from "http-status"; +import express from "express"; +import passport from "../lib/passport"; +import { LikeController } from "../controllers/likeController"; const router = express.Router(); +const controller = new LikeController(); -router.post( - "/like/articles/:id", - passport.authenticate("access-token", { session: false }), - likeArticle -); -router.post( - "/like/products/:id", - passport.authenticate("access-token", { session: false }), - likeProduct -); -router.get( - "/like/articles", - passport.authenticate("access-token", { session: false }), - getLikedArticles -); -router.get( - "/like/products", - passport.authenticate("access-token", { session: false }), - getLikedProducts -); +router.post("/articles/:id", passport.authenticate("access-token", { session: false }), controller.likeArticle); +router.post("/products/:id", passport.authenticate("access-token", { session: false }), controller.likeProduct); +router.get("/articles", passport.authenticate("access-token", { session: false }), controller.getLikedArticles); +router.get("/products", passport.authenticate("access-token", { session: false }), controller.getLikedProducts); -async function likeArticle(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - const user = req.user; - const articleId = Number(req.params.id); - - try { - const article = await prisma.article.findUnique({ - where: { id: articleId }, - }); - - if (!article) { - return res - .status(status.NOT_FOUND) - .json({ message: "Article not found" }); - } - const existing = await prisma.like.findUnique({ - where: { - userId_articleId: { userId: user.id, articleId }, - }, - }); - - if (existing) { - const updated = await prisma.like.update({ - where: { - userId_articleId: { userId: user.id, articleId }, - }, - data: { - like: !existing.like, - }, - }); - return res - .status(status.OK) - .json({ message: "Like toggled", isliked: updated.like }); - } else { - const created = await prisma.like.create({ - data: { - like: true, - articleId, - userId: user.id, - }, - }); - return res - .status(status.CREATED) - .json({ message: "Liked successfully", like: created.like }); - } - } catch (err) { - next(err); - } -} - -async function likeProduct(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - const user = req.user; - const productId = Number(req.params.id); - - try { - const product = await prisma.product.findUnique({ - where: { id: productId }, - }); - - if (!product) { - return res - .status(status.NOT_FOUND) - .json({ message: "Product not found" }); - } - - const existing = await prisma.like.findUnique({ - where: { - userId_productId: { userId: user.id, productId }, - }, - }); - - if (existing) { - const updated = await prisma.like.update({ - where: { - userId_productId: { userId: user.id, productId }, - }, - data: { - like: !existing.like, - }, - }); - return res - .status(status.OK) - .json({ message: "Like toggled", isLiked: updated.like }); - } else { - const created = await prisma.like.create({ - data: { - like: true, - productId, - userId: user.id, - }, - }); - return res - .status(status.CREATED) - .json({ message: "Liked successfully", isLiked: created.like }); - } - } catch (err) { - next(err); - } -} - -async function getLikedArticles(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - const user = req.user; - - try { - const likedArticles = await prisma.like.findMany({ - where: { - userId: user.id, - articleId: { not: null }, - like: true, - }, - include: { - article: { - select: { - id: true, - title: true, - }, - }, - }, - }); - - if (!likedArticles) { - return res - .status(status.NOT_FOUND) - .json({ message: "Articles not found" }); - } - - const articles = likedArticles.map((l) => ({ - ...l.article, - isLiked: true, - })); - - res.status(status.OK).json(articles); - } catch (err) { - next(err); - } -} - -async function getLikedProducts(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - const user = req.user; - - try { - const likedProducts = await prisma.like.findMany({ - where: { - userId: user.id, - productId: { not: null }, - like: true, - }, - include: { - product: { - select: { - id: true, - name: true, - price: true, - tags: true, - }, - }, - }, - }); - - if (!likedProducts) { - return res - .status(status.NOT_FOUND) - .json({ message: "Product not found" }); - } - - const products = likedProducts.map((l) => ({ - ...l.product, - isLiked: true, - })); - - res.status(status.OK).json(products); - } catch (err) { - next(err); - } -} - -export default router; +export default router; \ No newline at end of file diff --git a/mission5/src/routers/photoRouter.ts b/mission5/src/routers/photoRouter.ts index 12946d2b4..036f69e1a 100644 --- a/mission5/src/routers/photoRouter.ts +++ b/mission5/src/routers/photoRouter.ts @@ -1,39 +1,18 @@ import express from "express"; import multer from "multer"; -import passport from "../lib/passport/index"; -import prisma from "../lib/prisma"; -import status from "http-status"; +import passport from "../lib/passport"; +import { PhotoController } from "../controllers/photoController"; const router = express.Router(); const upload = multer({ dest: "uploads/" }); +const controller = new PhotoController(); +// ✅ 공통 업로드 엔드포인트 router.post( - "/users/photos", + "/", passport.authenticate("access-token", { session: false }), upload.single("image"), - async (req, res, next) => { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - const user = req.user; - - if (!req.file) { - return res.status(status.NOT_FOUND).json({ message: "No file upload" }); - } - - try { - const imageUrl = `/download/${req.file.filename}`; - const updatedUser = await prisma.user.update({ - where: { id: user.id }, - data: { image: imageUrl }, - }); - - res.status(status.OK).json({ - message: "Photo uploaded successfully", - image: updatedUser.image, - }); - } catch (err) { - next(err); - } - } + controller.upload ); export default router; diff --git a/mission5/src/routers/productRouter.ts b/mission5/src/routers/productRouter.ts index 0b28b891a..63f2d5d87 100644 --- a/mission5/src/routers/productRouter.ts +++ b/mission5/src/routers/productRouter.ts @@ -1,220 +1,14 @@ -import express, { type Request, type Response, type NextFunction } from "express"; -import prisma from "../lib/prisma"; -import passport from "../lib/passport/index"; -import { z } from "zod"; -import status from "http-status"; -import type { Prisma } from "@prisma/client"; +import express from "express"; +import passport from "../lib/passport"; +import { ProductController } from "../controllers/productController"; const router = express.Router(); +const controller = new ProductController(); -// body 검증 (상품 생성/수정) -const productSchema = z.object({ - //유효성 검사 설정하기 - name: z.string().min(1, { message: "이름을 입력해주세요" }), - description: z - .string() - .min(10, { message: "설명은 최소 10자 이상이어야 합니다." }) - .max(100, { message: "설명은 최대 100자까지 가능합니다." }), - price: z.number().int() - .positive({ message: "가격은 양의 정수여야 합니다." }), - tags: z.string().default("") -}); +router.post("/", passport.authenticate("access-token", { session: false }), controller.create); +router.get("/", controller.list); +router.get("/:id", passport.authenticate("access-token", { session: false }), controller.list); +router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update); +router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete); -// query 검증 (상품 조회) -const productQuerySchema = z.object({ - page: z - .string() - .default("1") - .transform(Number) - .refine((val) => val > 0, { message: "page는 1 이상의 정수여야 합니다." }), - pageSize: z - .string() - .default("5") - .transform(Number) - .refine((val) => val > 0 && val <= 100, { - message: "pageSize는 1~100 사이여야 합니다.", - }), - keyword: z.string().default(""), -}); - -router.post( - "/products", - passport.authenticate("access-token", { session: false }), - createProduct -); -router.get("/products", getProducts); -router.patch( - "/products/:id", - passport.authenticate("access-token", { session: false }), - modifyProduct -); -router.delete( - "/products/:id", - passport.authenticate("access-token", { session: false }), - deleteProduct -); -router.get( - "/products/:id", - passport.authenticate("access-token", { session: false }), - getDetailProduct -); - -async function createProduct(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - const parsed = productSchema.parse(req.body); - const user = req.user; - - try { - const createData = { - userId: user.id, - tags: parsed.tags, - ...(parsed.name && { name: parsed.name }), - ...(parsed.description && { description: parsed.description }), - ...(parsed.price && { price: parsed.price }), - } - const product = await prisma.product.create({ - data: { - ...parsed, - userId: req.user.id, // userId 추가 - }, - }); - - res.status(status.CREATED).json(product); - } catch (err) { - next(err); - } -} - -async function getProducts(req: Request, res: Response, next: NextFunction) { - const { page, pageSize, keyword } = productQuerySchema.parse(req.query); - const where: Prisma.ProductWhereInput = keyword //name과 description에서 원하는 keyword가 들어간 데이터를 찾도록 만든 변수 - ? { - OR: [ - { - name: { - contains: keyword, - mode: "insensitive" as const, //대소문자 구분 없이 검색하기 위해 - }, - }, - { - description: { - contains: keyword, - mode: "insensitive" as const, - }, - }, - ], - } - : {}; //기본값 {}으로 빈 객체를 수식하기 위함 - - try { - const products = await prisma.product.findMany({ - skip: (page - 1) * pageSize, - take: pageSize, - orderBy: { - // 최신 순서대로 정렬하기(최신순) - createdAt: "desc", - }, - select: { - id: true, - name: true, - description: true, - price: true, - tags: true, - createdAt: true, - }, - where, - }); - - res.status(status.OK).json(products); - } catch (err) { - next(err); - } -} - -async function modifyProduct(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - const productId = Number(req.params.id); - const parsed = productSchema.parse(req.body); - const user = req.user; - - try { - const product = await prisma.product.findUnique({ - where: { id: productId }, - }); - - if (!product) { - return res - .status(status.NOT_FOUND) - .json({ message: "Product not found" }); - } - if (product.userId !== user.id) { - return res.status(status.FORBIDDEN).json({ message: "User not matched" }); - } - - const updated = await prisma.product.update({ - where: { id: productId }, - data: { - ...parsed, - }, - }); - res.status(status.OK).json(updated); - } catch (err) { - next(err); - } -} - -async function deleteProduct(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - const productId = Number(req.params.id); - const user = req.user; - - try { - const product = await prisma.product.findUnique({ - where: { id: productId }, - }); - - if (!product) { - return res - .status(status.NOT_FOUND) - .json({ message: "Product not found" }); - } - if (product.userId !== user.id) { - return res.status(status.FORBIDDEN).json({ message: "User not matched" }); - } - - await prisma.product.delete({ - where: { id: productId }, - }); - res.status(status.NO_CONTENT).end(); - } catch (err) { - next(err); - } -} - -async function getDetailProduct(req: Request, res: Response, next: NextFunction) { - const productId = Number(req.params.id); - - try { - const product = await prisma.product.findUnique({ - where: { id: productId }, - select: { - id: true, - name: true, - description: true, - price: true, - tags: true, - createdAt: true, - }, - }); - - if (!product) { - return res.status(status.NOT_FOUND).json({ error: "Product not found" }); - } - - res.status(status.OK).json(product); - } catch (err) { - next(err); - } -} - -export default router; +export default router; \ No newline at end of file diff --git a/mission5/src/routers/userRouter.ts b/mission5/src/routers/userRouter.ts index d9443e019..0df2f4317 100644 --- a/mission5/src/routers/userRouter.ts +++ b/mission5/src/routers/userRouter.ts @@ -1,227 +1,17 @@ -import express, { Request, Response, NextFunction } from "express"; -import bcrypt from "bcrypt"; -import prisma from "../lib/prisma"; -import passport from "../lib/passport/index"; -import status from "http-status"; -import { generateTokens } from "../lib/token"; -import { - NODE_ENV, - ACCESS_TOKEN_COOKIE_NAME, - REFRESH_TOKEN_COOKIE_NAME, -} from "../lib/constants"; +import express from "express"; +import passport from "../lib/passport"; +import { UserController } from "../controllers/userController"; const router = express.Router(); - -router.post("/users/register", register); -router.post( - "/users/login", - passport.authenticate("local", { session: false }), - login -); -router.get( - "/users/profile", - passport.authenticate("access-token", { session: false }), - profile -); -router.patch( - "/users/modifyInformation", - passport.authenticate("access-token", { session: false }), - modifyinformation -); -router.patch( - "/users/modifyPassword", - passport.authenticate("access-token", { session: false }), - modifyPassword -); -router.get( - "/users/products", - passport.authenticate("access-token", { session: false }), - products -); -router.post( - "/users/refresh", - passport.authenticate("refresh-token", { session: false }), - refreshTokens -); -router.post("/users/logout", logout); - -async function register(req: Request, res: Response, next: NextFunction) { - const { email, nickname, password } = req.body; - - try { - const check = await prisma.user.findUnique({ where: { email } }); - if (check) { - return res - .status(status.CONFLICT) - .json({ message: "This ID already exists" }); - } - - const salt = await bcrypt.genSalt(10); - const hashedPassword = await bcrypt.hash(password, salt); - await prisma.user.create({ - data: { email, nickname, password: hashedPassword }, - }); - - res - .status(status.CREATED) - .json({ message: "User registered successfully" }); - } catch (err) { - next(err); - } -} - -function login(req: Request, res: Response, next: NextFunction) { - if (!req.user) { - return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); - } - - try { - const { accessToken, refreshToken } = generateTokens(req.user.id); - setTokenCookies(res, accessToken, refreshToken); - res.status(status.OK).json({ token: accessToken, refreshToken }); - } catch (err) { - next(err); - } -} - -async function profile(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - - try { - const profile = await prisma.user.findUnique({ - where: { - id: req.user.id, - }, - select: { - id: true, - email: true, - nickname: true, - image: true, - createdAt: true, - updatedAt: true, - }, - }); - res.status(status.OK).json(profile); - } catch (err) { - next(err); - } -} - -async function modifyinformation(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - const { nickname, image } = req.body as { nickname?: string; image?: string }; - - try { - const updateData: Record = {}; - if (nickname) updateData.nickname = nickname; - if (image) updateData.image = image; - - if (Object.keys(updateData).length === 0) { - return res - .status(status.BAD_REQUEST) - .json({ message: "No update data provided" }); - } - - const updatedUser = await prisma.user.update({ - where: { id: req.user.id }, - data: updateData, - select: { - id: true, - email: true, - nickname: true, - image: true, - createdAt: true, - }, - }); - - res.status(status.OK).json({ - message: "User information updated successfully", - user: updatedUser, - }); - } catch (err) { - next(err); - } -} - -async function modifyPassword(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - const { password } = req.body; - - try { - const salt = await bcrypt.genSalt(10); - const hashedPassword = await bcrypt.hash(password, salt); - - await prisma.user.update({ - where: { id: req.user.id }, - data: { - password: hashedPassword, - }, - }); - - res - .status(status.OK) - .json({ message: "User passowrd updated successfully" }); - } catch (err) { - next(err); - } -} - -async function products(req: Request, res: Response, next: NextFunction) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - - try { - const products = await prisma.product.findMany({ - where: { - userId: req.user.id, - }, - select: { - name: true, - description: true, - price: true, - tags: true, - }, - }); - if (!products) { - return res.status(status.NOT_FOUND).json({ message: "No product" }); - } - res.status(status.OK).json(products); - } catch (err) { - next(err); - } -} - -function logout(req: Request, res: Response) { - clearTokenCookies(res); - res.status(status.OK).send({ message: "Logged out successfully" }); -} - -async function refreshTokens(req: Request, res: Response) { - if (!req.user) return res.status(401).json({ message: "Unauthorized" }); - - const { accessToken, refreshToken: newRefreshToken } = generateTokens( - req.user.id - ); - setTokenCookies(res, accessToken, newRefreshToken); - res.status(status.OK).send({ message: "Tokens refreshed" }); -} - -function setTokenCookies(res: Response, accessToken: string, refreshToken: string) { - res.cookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, { - httpOnly: true, - secure: NODE_ENV === "production", - maxAge: 1 * 60 * 60 * 1000, // 1 hour - }); - res.cookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken, { - httpOnly: true, - secure: NODE_ENV === "production", - maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days - path: "/users/refresh", - }); -} - -function clearTokenCookies(res: Response) { - res.clearCookie(ACCESS_TOKEN_COOKIE_NAME); - res.clearCookie(REFRESH_TOKEN_COOKIE_NAME); -} - -export default router; \ No newline at end of file +const controller = new UserController(); + +router.post("/register", controller.register); +router.post("/login", passport.authenticate("local", { session: false }), controller.login); +router.get("/profile", passport.authenticate("access-token", { session: false }), controller.profile); +router.patch("/modifyInformation", passport.authenticate("access-token", { session: false }), controller.modifyInformation); +router.patch("/modifyPassword", passport.authenticate("access-token", { session: false }), controller.modifyPassword); +router.get("/products", passport.authenticate("access-token", { session: false }), controller.products); +router.post("/refresh", passport.authenticate("refresh-token", { session: false }), controller.refreshTokens); +router.post("/logout", controller.logout); + +export default router; diff --git a/mission5_dtos/src/services/articleService.ts b/mission5/src/services/articleService.ts similarity index 100% rename from mission5_dtos/src/services/articleService.ts rename to mission5/src/services/articleService.ts diff --git a/mission5_dtos/src/services/commentService.ts b/mission5/src/services/commentService.ts similarity index 100% rename from mission5_dtos/src/services/commentService.ts rename to mission5/src/services/commentService.ts diff --git a/mission5_dtos/src/services/likeService.ts b/mission5/src/services/likeService.ts similarity index 100% rename from mission5_dtos/src/services/likeService.ts rename to mission5/src/services/likeService.ts diff --git a/mission5_dtos/src/services/productService.ts b/mission5/src/services/productService.ts similarity index 100% rename from mission5_dtos/src/services/productService.ts rename to mission5/src/services/productService.ts diff --git a/mission5_dtos/src/services/userService.ts b/mission5/src/services/userService.ts similarity index 100% rename from mission5_dtos/src/services/userService.ts rename to mission5/src/services/userService.ts diff --git a/mission5/src/types/express.d.ts b/mission5/src/types/express.d.ts index c8caae71e..6f994ace7 100644 --- a/mission5/src/types/express.d.ts +++ b/mission5/src/types/express.d.ts @@ -8,4 +8,4 @@ declare global { } // 반드시 export {} 필요 -export {}; \ No newline at end of file +export {}; \ No newline at end of file diff --git a/mission5_dtos/.gitignore b/mission5_dtos/.gitignore deleted file mode 100644 index 9f62ec0b8..000000000 --- a/mission5_dtos/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -node_modules -# Keep environment variables out of version control -.env - -/generated/prisma diff --git a/mission5_dtos/package-lock.json b/mission5_dtos/package-lock.json deleted file mode 100644 index 4b76c5e8d..000000000 --- a/mission5_dtos/package-lock.json +++ /dev/null @@ -1,3128 +0,0 @@ -{ - "name": "mission3", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "mission3", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "@prisma/client": "^6.13.0", - "bcrypt": "^6.0.0", - "cookie-parser": "^1.4.7", - "cors": "^2.8.5", - "dotenv": "^17.2.2", - "express": "^5.1.0", - "http-status": "^2.1.0", - "multer": "^2.0.2", - "passport": "^0.7.0", - "passport-jwt": "^4.0.1", - "passport-local": "^1.0.0", - "tsx": "^4.20.5", - "zod": "^4.0.14" - }, - "devDependencies": { - "@types/bcrypt": "^6.0.0", - "@types/cookie-parser": "^1.4.9", - "@types/cors": "^2.8.19", - "@types/express": "^5.0.3", - "@types/jsonwebtoken": "^9.0.10", - "@types/multer": "^2.0.0", - "@types/node": "^24.3.1", - "@types/passport": "^1.0.17", - "@types/passport-jwt": "^4.0.1", - "@types/passport-local": "^1.0.38", - "prisma": "^6.15.0", - "ts-node": "^10.9.2", - "ts-node-dev": "^2.0.0", - "typescript": "^5.9.2" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", - "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", - "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", - "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", - "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", - "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", - "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", - "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", - "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", - "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", - "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", - "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", - "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", - "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", - "cpu": [ - "mips64el" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", - "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", - "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", - "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", - "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", - "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", - "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", - "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", - "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", - "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", - "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", - "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", - "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", - "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@prisma/client": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.13.0.tgz", - "integrity": "sha512-8m2+I3dQovkV8CkDMluiwEV1TxV9EXdT6xaCz39O6jYw7mkf5gwfmi+cL4LJsEPwz5tG7sreBwkRpEMJedGYUQ==", - "hasInstallScript": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "peerDependencies": { - "prisma": "*", - "typescript": ">=5.1.0" - }, - "peerDependenciesMeta": { - "prisma": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/@prisma/config": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.15.0.tgz", - "integrity": "sha512-KMEoec9b2u6zX0EbSEx/dRpx1oNLjqJEBZYyK0S3TTIbZ7GEGoVyGyFRk4C72+A38cuPLbfQGQvgOD+gBErKlA==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "c12": "3.1.0", - "deepmerge-ts": "7.1.5", - "effect": "3.16.12", - "empathic": "2.0.0" - } - }, - "node_modules/@prisma/debug": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.15.0.tgz", - "integrity": "sha512-y7cSeLuQmyt+A3hstAs6tsuAiVXSnw9T55ra77z0nbNkA8Lcq9rNcQg6PI00by/+WnE/aMRJ/W7sZWn2cgIy1g==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@prisma/engines": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.15.0.tgz", - "integrity": "sha512-opITiR5ddFJ1N2iqa7mkRlohCZqVSsHhRcc29QXeldMljOf4FSellLT0J5goVb64EzRTKcIDeIsJBgmilNcKxA==", - "devOptional": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "6.15.0", - "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", - "@prisma/fetch-engine": "6.15.0", - "@prisma/get-platform": "6.15.0" - } - }, - "node_modules/@prisma/engines-version": { - "version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb.tgz", - "integrity": "sha512-a/46aK5j6L3ePwilZYEgYDPrhBQ/n4gYjLxT5YncUTJJNRnTCVjPF86QdzUOLRdYjCLfhtZp9aum90W0J+trrg==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@prisma/fetch-engine": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.15.0.tgz", - "integrity": "sha512-xcT5f6b+OWBq6vTUnRCc7qL+Im570CtwvgSj+0MTSGA1o9UDSKZ/WANvwtiRXdbYWECpyC3CukoG3A04VTAPHw==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "6.15.0", - "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", - "@prisma/get-platform": "6.15.0" - } - }, - "node_modules/@prisma/get-platform": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.15.0.tgz", - "integrity": "sha512-Jbb+Xbxyp05NSR1x2epabetHiXvpO8tdN2YNoWoA/ZsbYyxxu/CO/ROBauIFuMXs3Ti+W7N7SJtWsHGaWte9Rg==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "6.15.0" - } - }, - "node_modules/@standard-schema/spec": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", - "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/bcrypt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-6.0.0.tgz", - "integrity": "sha512-/oJGukuH3D2+D+3H4JWLaAsJ/ji86dhRidzZ/Od7H/i8g+aCmvkeCc6Ni/f9uxGLSQVCRZkX2/lqEFG2BvWtlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.6", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", - "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/cookie-parser": { - "version": "1.4.9", - "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.9.tgz", - "integrity": "sha512-tGZiZ2Gtc4m3wIdLkZ8mkj1T6CEHb35+VApbL2T14Dew8HA7c+04dmKqsKRNC+8RJPm16JEK0tFSwdZqubfc4g==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/cors": { - "version": "2.8.19", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", - "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/express": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz", - "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^5.0.0", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", - "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/http-errors": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", - "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/jsonwebtoken": { - "version": "9.0.10", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", - "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/ms": "*", - "@types/node": "*" - } - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/multer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz", - "integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/node": { - "version": "24.3.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz", - "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.10.0" - } - }, - "node_modules/@types/passport": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", - "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/passport-jwt": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-4.0.1.tgz", - "integrity": "sha512-Y0Ykz6nWP4jpxgEUYq8NoVZeCQPo1ZndJLfapI249g1jHChvRfZRO/LS3tqu26YgAS/laI1qx98sYGz0IalRXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/jsonwebtoken": "*", - "@types/passport-strategy": "*" - } - }, - "node_modules/@types/passport-local": { - "version": "1.0.38", - "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.38.tgz", - "integrity": "sha512-nsrW4A963lYE7lNTv9cr5WmiUD1ibYJvWrpE13oxApFsRt77b0RdtZvKbCdNIY4v/QZ6TRQWaDDEwV1kCTmcXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*", - "@types/passport": "*", - "@types/passport-strategy": "*" - } - }, - "node_modules/@types/passport-strategy": { - "version": "0.2.38", - "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", - "integrity": "sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*", - "@types/passport": "*" - } - }, - "node_modules/@types/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/send": { - "version": "0.17.5", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", - "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.8", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", - "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" - } - }, - "node_modules/@types/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/strip-json-comments": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", - "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "license": "MIT", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "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==", - "license": "MIT" - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "license": "MIT" - }, - "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, - "license": "MIT" - }, - "node_modules/bcrypt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", - "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "node-addon-api": "^8.3.0", - "node-gyp-build": "^4.8.4" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/body-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", - "license": "MIT", - "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.0", - "http-errors": "^2.0.0", - "iconv-lite": "^0.6.3", - "on-finished": "^2.4.1", - "qs": "^6.14.0", - "raw-body": "^3.0.0", - "type-is": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "BSD-3-Clause" - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "license": "MIT" - }, - "node_modules/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==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/c12": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", - "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "chokidar": "^4.0.3", - "confbox": "^0.2.2", - "defu": "^6.1.4", - "dotenv": "^16.6.1", - "exsolve": "^1.0.7", - "giget": "^2.0.0", - "jiti": "^2.4.2", - "ohash": "^2.0.11", - "pathe": "^2.0.3", - "perfect-debounce": "^1.0.0", - "pkg-types": "^2.2.0", - "rc9": "^2.1.2" - }, - "peerDependencies": { - "magicast": "^0.3.5" - }, - "peerDependenciesMeta": { - "magicast": { - "optional": true - } - } - }, - "node_modules/c12/node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "devOptional": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/citty": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", - "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "consola": "^3.2.3" - } - }, - "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, - "license": "MIT" - }, - "node_modules/concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "engines": [ - "node >= 6.0" - ], - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/confbox": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", - "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/consola": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", - "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": "^14.18.0 || >=16.10.0" - } - }, - "node_modules/content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", - "license": "MIT", - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-parser": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", - "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", - "license": "MIT", - "dependencies": { - "cookie": "0.7.2", - "cookie-signature": "1.0.6" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/cookie-parser/node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "license": "MIT" - }, - "node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "license": "MIT", - "engines": { - "node": ">=6.6.0" - } - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "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, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deepmerge-ts": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", - "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", - "devOptional": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/defu": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", - "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dotenv": { - "version": "17.2.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", - "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/dynamic-dedupe": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", - "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "xtend": "^4.0.0" - } - }, - "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==", - "license": "Apache-2.0", - "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", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/effect": { - "version": "3.16.12", - "resolved": "https://registry.npmjs.org/effect/-/effect-3.16.12.tgz", - "integrity": "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "fast-check": "^3.23.1" - } - }, - "node_modules/empathic": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", - "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", - "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.9", - "@esbuild/android-arm": "0.25.9", - "@esbuild/android-arm64": "0.25.9", - "@esbuild/android-x64": "0.25.9", - "@esbuild/darwin-arm64": "0.25.9", - "@esbuild/darwin-x64": "0.25.9", - "@esbuild/freebsd-arm64": "0.25.9", - "@esbuild/freebsd-x64": "0.25.9", - "@esbuild/linux-arm": "0.25.9", - "@esbuild/linux-arm64": "0.25.9", - "@esbuild/linux-ia32": "0.25.9", - "@esbuild/linux-loong64": "0.25.9", - "@esbuild/linux-mips64el": "0.25.9", - "@esbuild/linux-ppc64": "0.25.9", - "@esbuild/linux-riscv64": "0.25.9", - "@esbuild/linux-s390x": "0.25.9", - "@esbuild/linux-x64": "0.25.9", - "@esbuild/netbsd-arm64": "0.25.9", - "@esbuild/netbsd-x64": "0.25.9", - "@esbuild/openbsd-arm64": "0.25.9", - "@esbuild/openbsd-x64": "0.25.9", - "@esbuild/openharmony-arm64": "0.25.9", - "@esbuild/sunos-x64": "0.25.9", - "@esbuild/win32-arm64": "0.25.9", - "@esbuild/win32-ia32": "0.25.9", - "@esbuild/win32-x64": "0.25.9" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", - "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", - "license": "MIT", - "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.0", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/exsolve": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", - "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/fast-check": { - "version": "3.23.2", - "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", - "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", - "devOptional": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT", - "dependencies": { - "pure-rand": "^6.1.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", - "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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, - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "license": "MIT", - "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==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-tsconfig": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", - "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/giget": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", - "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "citty": "^0.1.6", - "consola": "^3.4.0", - "defu": "^6.1.4", - "node-fetch-native": "^1.6.6", - "nypm": "^0.6.0", - "pathe": "^2.0.3" - }, - "bin": { - "giget": "dist/cli.mjs" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "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/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, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-status": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-status/-/http-status-2.1.0.tgz", - "integrity": "sha512-O5kPr7AW7wYd/BBiOezTwnVAnmSNFY+J7hlZD2X5IOxVBetjcHAiTXhzj0gMrnojQlwy+UT1/Y3H3vJ3UlmvLA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 0.4.0" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "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==", - "license": "ISC" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "license": "MIT" - }, - "node_modules/jiti": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", - "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", - "devOptional": true, - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", - "license": "MIT", - "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.2", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", - "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", - "license": "MIT", - "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==", - "license": "MIT", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "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==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", - "license": "MIT" - }, - "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, - "license": "ISC" - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">= 0.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, - "license": "ISC", - "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==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "license": "MIT", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/multer": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", - "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", - "license": "MIT", - "dependencies": { - "append-field": "^1.0.0", - "busboy": "^1.6.0", - "concat-stream": "^2.0.0", - "mkdirp": "^0.5.6", - "object-assign": "^4.1.1", - "type-is": "^1.6.18", - "xtend": "^4.0.2" - }, - "engines": { - "node": ">= 10.16.0" - } - }, - "node_modules/multer/node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/multer/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/multer/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/multer/node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/node-addon-api": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz", - "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==", - "license": "MIT", - "engines": { - "node": "^18 || ^20 || >= 21" - } - }, - "node_modules/node-fetch-native": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", - "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/node-gyp-build": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", - "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", - "license": "MIT", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nypm": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.1.tgz", - "integrity": "sha512-hlacBiRiv1k9hZFiphPUkfSQ/ZfQzZDzC+8z0wL3lvDAOUu/2NnChkKuMoMjNur/9OpKuz2QsIeiPVN0xM5Q0w==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "citty": "^0.1.6", - "consola": "^3.4.2", - "pathe": "^2.0.3", - "pkg-types": "^2.2.0", - "tinyexec": "^1.0.1" - }, - "bin": { - "nypm": "dist/cli.mjs" - }, - "engines": { - "node": "^14.16.0 || >=16.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ohash": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", - "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "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==", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/passport": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", - "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", - "license": "MIT", - "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-jwt": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", - "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", - "license": "MIT", - "dependencies": { - "jsonwebtoken": "^9.0.0", - "passport-strategy": "^1.0.0" - } - }, - "node_modules/passport-local": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", - "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", - "dependencies": { - "passport-strategy": "1.x.x" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "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-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, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "license": "MIT" - }, - "node_modules/path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "license": "MIT", - "engines": { - "node": ">=16" - } - }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/pause": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" - }, - "node_modules/perfect-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", - "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pkg-types": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", - "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "confbox": "^0.2.2", - "exsolve": "^1.0.7", - "pathe": "^2.0.3" - } - }, - "node_modules/prisma": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.15.0.tgz", - "integrity": "sha512-E6RCgOt+kUVtjtZgLQDBJ6md2tDItLJNExwI0XJeBc1FKL+Vwb+ovxXxuok9r8oBgsOXBA33fGDuE/0qDdCWqQ==", - "devOptional": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/config": "6.15.0", - "@prisma/engines": "6.15.0" - }, - "bin": { - "prisma": "build/index.js" - }, - "engines": { - "node": ">=18.18" - }, - "peerDependencies": { - "typescript": ">=5.1.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", - "devOptional": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, - "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", - "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.6.3", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/rc9": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", - "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "defu": "^6.1.4", - "destr": "^2.0.3" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/router": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "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" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", - "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", - "license": "MIT", - "dependencies": { - "debug": "^4.3.5", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "mime-types": "^3.0.1", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", - "license": "MIT", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tinyexec": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", - "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", - "devOptional": true, - "license": "MIT" - }, - "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, - "license": "MIT", - "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==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "license": "MIT", - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, - "license": "MIT", - "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/ts-node-dev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz", - "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^3.5.1", - "dynamic-dedupe": "^0.3.0", - "minimist": "^1.2.6", - "mkdirp": "^1.0.4", - "resolve": "^1.0.0", - "rimraf": "^2.6.1", - "source-map-support": "^0.5.12", - "tree-kill": "^1.2.2", - "ts-node": "^10.4.0", - "tsconfig": "^7.0.0" - }, - "bin": { - "ts-node-dev": "lib/bin.js", - "tsnd": "lib/bin.js" - }, - "engines": { - "node": ">=0.8.0" - }, - "peerDependencies": { - "node-notifier": "*", - "typescript": "*" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/ts-node-dev/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "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" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/ts-node-dev/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ts-node-dev/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/tsconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", - "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/strip-bom": "^3.0.0", - "@types/strip-json-comments": "0.0.30", - "strip-bom": "^3.0.0", - "strip-json-comments": "^2.0.0" - } - }, - "node_modules/tsx": { - "version": "4.20.5", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.5.tgz", - "integrity": "sha512-+wKjMNU9w/EaQayHXb7WA7ZaHY6hN8WgfvHNQ3t1PnU91/7O8TcTnIhCDYTZwnt8JsO9IBqZ30Ln1r7pPF52Aw==", - "license": "MIT", - "dependencies": { - "esbuild": "~0.25.0", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", - "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "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==", - "license": "MIT" - }, - "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", - "devOptional": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", - "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", - "dev": true, - "license": "MIT" - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "license": "MIT" - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/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, - "license": "MIT" - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "license": "ISC" - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/zod": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.0.14.tgz", - "integrity": "sha512-nGFJTnJN6cM2v9kXL+SOBq3AtjQby3Mv5ySGFof5UGRHrRioSJ5iG680cYNjE/yWk671nROcpPj4hAS8nyLhSw==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - } - } -} diff --git a/mission5_dtos/package.json b/mission5_dtos/package.json deleted file mode 100644 index a68267d04..000000000 --- a/mission5_dtos/package.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "name": "mission3", - "version": "1.0.0", - "main": "index.js", - "scripts": { - "dev": "ts-node --files src/app.ts", - "start": "node dist/app.js", - "lint": "eslint . --ext .ts", - "prisma:generate": "prisma generate", - "prisma:migrate": "prisma migrate dev" - }, - "author": "", - "license": "ISC", - "description": "", - "dependencies": { - "@prisma/client": "^6.13.0", - "bcrypt": "^6.0.0", - "cookie-parser": "^1.4.7", - "cors": "^2.8.5", - "dotenv": "^17.2.2", - "express": "^5.1.0", - "http-status": "^2.1.0", - "multer": "^2.0.2", - "passport": "^0.7.0", - "passport-jwt": "^4.0.1", - "passport-local": "^1.0.0", - "tsx": "^4.20.5", - "zod": "^4.0.14" - }, - "devDependencies": { - "@types/bcrypt": "^6.0.0", - "@types/cookie-parser": "^1.4.9", - "@types/cors": "^2.8.19", - "@types/express": "^5.0.3", - "@types/jsonwebtoken": "^9.0.10", - "@types/multer": "^2.0.0", - "@types/node": "^24.3.1", - "@types/passport": "^1.0.17", - "@types/passport-jwt": "^4.0.1", - "@types/passport-local": "^1.0.38", - "prisma": "^6.15.0", - "ts-node": "^10.9.2", - "ts-node-dev": "^2.0.0", - "typescript": "^5.9.2" - }, - "prisma": { - "seed": "node prisma/seed.js" - } -} diff --git a/mission5_dtos/prisma/migrations/20250904083711_test/migration.sql b/mission5_dtos/prisma/migrations/20250904083711_test/migration.sql deleted file mode 100644 index ad7fbdc5d..000000000 --- a/mission5_dtos/prisma/migrations/20250904083711_test/migration.sql +++ /dev/null @@ -1,94 +0,0 @@ --- CreateTable -CREATE TABLE "public"."User" ( - "id" SERIAL NOT NULL, - "email" TEXT NOT NULL, - "nickname" TEXT NOT NULL, - "image" TEXT, - "password" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "User_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "public"."Product" ( - "id" SERIAL NOT NULL, - "name" TEXT NOT NULL, - "description" TEXT NOT NULL, - "price" INTEGER NOT NULL, - "tags" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "userId" INTEGER NOT NULL, - - CONSTRAINT "Product_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "public"."Article" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - "content" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "userId" INTEGER NOT NULL, - - CONSTRAINT "Article_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "public"."Comment" ( - "id" SERIAL NOT NULL, - "content" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "productId" INTEGER, - "articleId" INTEGER, - "userId" INTEGER NOT NULL, - - CONSTRAINT "Comment_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "public"."Like" ( - "id" SERIAL NOT NULL, - "like" BOOLEAN NOT NULL DEFAULT true, - "userId" INTEGER NOT NULL, - "productId" INTEGER, - "articleId" INTEGER, - - CONSTRAINT "Like_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "User_email_key" ON "public"."User"("email"); - --- CreateIndex -CREATE UNIQUE INDEX "Like_userId_productId_key" ON "public"."Like"("userId", "productId"); - --- CreateIndex -CREATE UNIQUE INDEX "Like_userId_articleId_key" ON "public"."Like"("userId", "articleId"); - --- AddForeignKey -ALTER TABLE "public"."Product" ADD CONSTRAINT "Product_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "public"."Article" ADD CONSTRAINT "Article_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_productId_fkey" FOREIGN KEY ("productId") REFERENCES "public"."Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "public"."Article"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_productId_fkey" FOREIGN KEY ("productId") REFERENCES "public"."Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "public"."Article"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/mission5_dtos/prisma/migrations/migration_lock.toml b/mission5_dtos/prisma/migrations/migration_lock.toml deleted file mode 100644 index 044d57cdb..000000000 --- a/mission5_dtos/prisma/migrations/migration_lock.toml +++ /dev/null @@ -1,3 +0,0 @@ -# Please do not edit this file manually -# It should be added in your version-control system (e.g., Git) -provider = "postgresql" diff --git a/mission5_dtos/prisma/schema.prisma b/mission5_dtos/prisma/schema.prisma deleted file mode 100644 index 05365cc8e..000000000 --- a/mission5_dtos/prisma/schema.prisma +++ /dev/null @@ -1,75 +0,0 @@ -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} - -generator client { - provider = "prisma-client-js" -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - nickname String - image String? - password String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - article Article[] - product Product[] - comment Comment[] - like Like[] -} - -model Product { - id Int @id @default(autoincrement()) - name String - description String - price Int - tags String? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - comment Comment[] - userId Int - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - like Like[] -} - -model Article { - id Int @id @default(autoincrement()) - title String - content String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - comment Comment[] - userId Int - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - like Like[] -} - -model Comment { - id Int @id @default(autoincrement()) - content String - createdAt DateTime @default(now()) - productId Int? - product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) - articleId Int? - article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) - userId Int - user User @relation(fields: [userId], references: [id], onDelete: Cascade) -} - -model Like { - id Int @id @default(autoincrement()) - like Boolean @default(true) - userId Int - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - productId Int? - product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) - articleId Int? - article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) - - // 유저-상품, 유저-게시글 각각 중복 방지, 좋아요 중첩 방지 - @@unique([userId, productId]) - @@unique([userId, articleId]) -} \ No newline at end of file diff --git a/mission5_dtos/src/app.ts b/mission5_dtos/src/app.ts deleted file mode 100644 index 9be0a16ce..000000000 --- a/mission5_dtos/src/app.ts +++ /dev/null @@ -1,31 +0,0 @@ -import express from "express"; -import cookieParser from "cookie-parser"; -import router from "./routers/index"; -import { PORT } from "./lib/constants"; -import passport from "./lib/passport/index"; -import cors from "cors"; -import { errorHandler } from "./middlewares/errorHandler"; - -const app = express(); - -app.use(express.urlencoded({ extended: true })); - -app.use(express.json()); -app.use(cookieParser()); -const corsOptions = { - //CORS 설정 및 whitelist로 'http://localhost:3000'을 설정 - origin: "http://localhost:3000", - optionSuccessStatus: 200, -}; - -app.use(cors(corsOptions)); -app.use(passport.initialize()); -app.use(router); -app.use("/download", express.static("uploads")); - - -app.use(errorHandler); - -app.listen(PORT, () => { - console.log(`Server is running on http://localhost:${PORT}`); -}); diff --git a/mission5_dtos/src/lib/constants.ts b/mission5_dtos/src/lib/constants.ts deleted file mode 100644 index af8e48a99..000000000 --- a/mission5_dtos/src/lib/constants.ts +++ /dev/null @@ -1,21 +0,0 @@ -import dotenv from 'dotenv'; - -dotenv.config(); - -const NODE_ENV = process.env.NODE_ENV || 'development'; -const PORT = process.env.PORT || 3000; -const JWT_ACCESS_TOKEN_SECRET = - process.env.JWT_ACCESS_TOKEN_SECRET || 'your_jwt_access_token_secret'; -const JWT_REFRESH_TOKEN_SECRET = - process.env.JWT_REFRESH_TOKEN_SECRET || 'your_jwt_refresh_token_secret'; -const ACCESS_TOKEN_COOKIE_NAME = 'access-token'; -const REFRESH_TOKEN_COOKIE_NAME = 'refresh-token'; - -export { - NODE_ENV, - PORT, - JWT_ACCESS_TOKEN_SECRET, - JWT_REFRESH_TOKEN_SECRET, - ACCESS_TOKEN_COOKIE_NAME, - REFRESH_TOKEN_COOKIE_NAME, -}; diff --git a/mission5_dtos/src/lib/passport/index.ts b/mission5_dtos/src/lib/passport/index.ts deleted file mode 100644 index 771eb1518..000000000 --- a/mission5_dtos/src/lib/passport/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import passport from 'passport'; -import { localStrategy } from './localStrategy'; -import { accessTokenStrategy, refreshTokenStrategy } from './jwtStrategy'; - -passport.use('local', localStrategy); -passport.use('access-token', accessTokenStrategy); -passport.use('refresh-token', refreshTokenStrategy); - -export default passport; diff --git a/mission5_dtos/src/lib/passport/jwtStrategy.ts b/mission5_dtos/src/lib/passport/jwtStrategy.ts deleted file mode 100644 index 7d258318c..000000000 --- a/mission5_dtos/src/lib/passport/jwtStrategy.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Strategy as JwtStrategy } from 'passport-jwt'; -import prisma from '../prisma'; -import type { Request } from 'express'; -import type { VerifiedCallback } from 'passport-jwt'; -import { - ACCESS_TOKEN_COOKIE_NAME, - REFRESH_TOKEN_COOKIE_NAME, - JWT_ACCESS_TOKEN_SECRET, - JWT_REFRESH_TOKEN_SECRET, -} from '../constants'; - -interface JwtPayload { - sub: number; -} - -const accessTokenOptions = { - jwtFromRequest: (req: Request) => req.cookies[ACCESS_TOKEN_COOKIE_NAME], - secretOrKey: JWT_ACCESS_TOKEN_SECRET, -}; - -const refreshTokenOptions = { - jwtFromRequest: (req: Request) => req.cookies[REFRESH_TOKEN_COOKIE_NAME], - secretOrKey: JWT_REFRESH_TOKEN_SECRET, -}; - -async function jwtVerify(payload: JwtPayload, done: VerifiedCallback) { - try { - const user = await prisma.user.findUnique({ - where: { id: payload.sub }, - }); - done(null, user); - } catch (error) { - done(error, false); - } -} - -export const accessTokenStrategy = new JwtStrategy( - accessTokenOptions, - jwtVerify -); - -export const refreshTokenStrategy = new JwtStrategy( - refreshTokenOptions, - jwtVerify -); diff --git a/mission5_dtos/src/lib/passport/localStrategy.ts b/mission5_dtos/src/lib/passport/localStrategy.ts deleted file mode 100644 index 3c3e7ba10..000000000 --- a/mission5_dtos/src/lib/passport/localStrategy.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Strategy as LocalStrategy } from "passport-local"; -import bcrypt from "bcrypt"; -import prisma from "../prisma"; - -export const localStrategy = new LocalStrategy( - { - usernameField: "email", // email을 localStrategy의 고정값 'username' 대신 쓰도록 지정 - passwordField: "password", - }, - async (email, password, done) => { - try { - const user = await prisma.user.findUnique({ where: { email } }); - if (!user) { - return done(null, false, { message: "No user found" }); - } - - const isPasswordValid = await bcrypt.compare(password, user.password); - if (!isPasswordValid) { - return done(null, false, { message: "Invalid password" }); - } - - return done(null, user); - } catch (err) { - return done(err); - } - } -); diff --git a/mission5_dtos/src/lib/prisma.ts b/mission5_dtos/src/lib/prisma.ts deleted file mode 100644 index b904402d2..000000000 --- a/mission5_dtos/src/lib/prisma.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { PrismaClient } from '@prisma/client'; - -const prisma = new PrismaClient(); - -export default prisma; \ No newline at end of file diff --git a/mission5_dtos/src/lib/token.ts b/mission5_dtos/src/lib/token.ts deleted file mode 100644 index 79a05e281..000000000 --- a/mission5_dtos/src/lib/token.ts +++ /dev/null @@ -1,27 +0,0 @@ -import jwt from 'jsonwebtoken'; -import { - JWT_ACCESS_TOKEN_SECRET, - JWT_REFRESH_TOKEN_SECRET, -} from './constants'; - -function generateTokens(userId: number) { - const accessToken = jwt.sign({ sub: userId }, JWT_ACCESS_TOKEN_SECRET, { - expiresIn: '1h', - }); - const refreshToken = jwt.sign({ sub: userId }, JWT_REFRESH_TOKEN_SECRET, { - expiresIn: '1d', - }); - return { accessToken, refreshToken }; -} - -function verifyAccessToken(token: string) { - const decoded = jwt.verify(token, JWT_ACCESS_TOKEN_SECRET); - return { userId: decoded.sub }; -} - -function verifyRefreshToken(token: string) { - const decoded = jwt.verify(token, JWT_REFRESH_TOKEN_SECRET); - return { userId: decoded.sub }; -} - -export { generateTokens, verifyAccessToken, verifyRefreshToken }; diff --git a/mission5_dtos/src/middlewares/errorHandler.ts b/mission5_dtos/src/middlewares/errorHandler.ts deleted file mode 100644 index dcaa5aaf3..000000000 --- a/mission5_dtos/src/middlewares/errorHandler.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { z } from "zod"; -import httpStatus from "http-status"; -import express , { type Request, type Response, type NextFunction } from "express"; - -interface ExtendedError extends Error { - code?: string; -} - -export function errorHandler(err: ExtendedError, req: Request, res: Response, next: NextFunction) { - if (err instanceof z.ZodError) { - return res.status(httpStatus.BAD_REQUEST).json({ error: err.issues }); - } - - if (err.code === "P2025") { - return res.status(httpStatus.NOT_FOUND).json({ error: "Record not found" }); - } - - console.error("unhandled Error:", err); - return res - .status(httpStatus.INTERNAL_SERVER_ERROR) - .json({ error: "Internal Server Error" }); -} diff --git a/mission5_dtos/src/routers/articleRouter.ts b/mission5_dtos/src/routers/articleRouter.ts deleted file mode 100644 index 4c4161a6b..000000000 --- a/mission5_dtos/src/routers/articleRouter.ts +++ /dev/null @@ -1,14 +0,0 @@ -import express from "express"; -import passport from "../lib/passport"; -import { ArticleController } from "../controllers/articleController"; - -const router = express.Router(); -const controller = new ArticleController(); - -router.post("/", passport.authenticate("access-token", { session: false }), controller.create); -router.get("/", passport.authenticate("access-token", { session: false }), controller.list); -router.get("/:id", passport.authenticate("access-token", { session: false }), controller.detail); -router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update); -router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete); - -export default router; \ No newline at end of file diff --git a/mission5_dtos/src/routers/commentRouter.ts b/mission5_dtos/src/routers/commentRouter.ts deleted file mode 100644 index f7b6b4903..000000000 --- a/mission5_dtos/src/routers/commentRouter.ts +++ /dev/null @@ -1,15 +0,0 @@ -import express from "express"; -import passport from "../lib/passport"; -import { CommentController } from "../controllers/commentController"; - -const router = express.Router(); -const controller = new CommentController(); - -router.post("/products/:id", passport.authenticate("access-token", { session: false }), controller.createProductComment); -router.post("/articles/:id", passport.authenticate("access-token", { session: false }), controller.createArticleComment); -router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.modifyComment); -router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.deleteComment); -router.get("/products/:id", passport.authenticate("access-token", { session: false }), controller.productCommentList); -router.get("/articles/:id", passport.authenticate("access-token", { session: false }), controller.articleCommentList); - -export default router; \ No newline at end of file diff --git a/mission5_dtos/src/routers/index.ts b/mission5_dtos/src/routers/index.ts deleted file mode 100644 index c1bafd4f0..000000000 --- a/mission5_dtos/src/routers/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -import express from "express"; - -import userRouter from "./userRouter"; -import articleRouter from "./articleRouter"; -import productRouter from "./productRouter"; -import commentRouter from "./commentRouter"; -import likeRouter from "./likeRouter"; -import photoRouter from "./photoRouter"; // ✅ 공통 업로드 전용 - -const router = express.Router(); - -router.use("/users", userRouter); -router.use("/articles", articleRouter); -router.use("/products", productRouter); -router.use("/comments", commentRouter); -router.use("/likes", likeRouter); -router.use(photoRouter); // 📌 prefix는 /photos - -export default router; \ No newline at end of file diff --git a/mission5_dtos/src/routers/likeRouter.ts b/mission5_dtos/src/routers/likeRouter.ts deleted file mode 100644 index 10ec9924d..000000000 --- a/mission5_dtos/src/routers/likeRouter.ts +++ /dev/null @@ -1,13 +0,0 @@ -import express from "express"; -import passport from "../lib/passport"; -import { LikeController } from "../controllers/likeController"; - -const router = express.Router(); -const controller = new LikeController(); - -router.post("/articles/:id", passport.authenticate("access-token", { session: false }), controller.likeArticle); -router.post("/products/:id", passport.authenticate("access-token", { session: false }), controller.likeProduct); -router.get("/articles", passport.authenticate("access-token", { session: false }), controller.getLikedArticles); -router.get("/products", passport.authenticate("access-token", { session: false }), controller.getLikedProducts); - -export default router; \ No newline at end of file diff --git a/mission5_dtos/src/routers/photoRouter.ts b/mission5_dtos/src/routers/photoRouter.ts deleted file mode 100644 index 036f69e1a..000000000 --- a/mission5_dtos/src/routers/photoRouter.ts +++ /dev/null @@ -1,18 +0,0 @@ -import express from "express"; -import multer from "multer"; -import passport from "../lib/passport"; -import { PhotoController } from "../controllers/photoController"; - -const router = express.Router(); -const upload = multer({ dest: "uploads/" }); -const controller = new PhotoController(); - -// ✅ 공통 업로드 엔드포인트 -router.post( - "/", - passport.authenticate("access-token", { session: false }), - upload.single("image"), - controller.upload -); - -export default router; diff --git a/mission5_dtos/src/routers/productRouter.ts b/mission5_dtos/src/routers/productRouter.ts deleted file mode 100644 index 63f2d5d87..000000000 --- a/mission5_dtos/src/routers/productRouter.ts +++ /dev/null @@ -1,14 +0,0 @@ -import express from "express"; -import passport from "../lib/passport"; -import { ProductController } from "../controllers/productController"; - -const router = express.Router(); -const controller = new ProductController(); - -router.post("/", passport.authenticate("access-token", { session: false }), controller.create); -router.get("/", controller.list); -router.get("/:id", passport.authenticate("access-token", { session: false }), controller.list); -router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update); -router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete); - -export default router; \ No newline at end of file diff --git a/mission5_dtos/src/routers/userRouter.ts b/mission5_dtos/src/routers/userRouter.ts deleted file mode 100644 index 0df2f4317..000000000 --- a/mission5_dtos/src/routers/userRouter.ts +++ /dev/null @@ -1,17 +0,0 @@ -import express from "express"; -import passport from "../lib/passport"; -import { UserController } from "../controllers/userController"; - -const router = express.Router(); -const controller = new UserController(); - -router.post("/register", controller.register); -router.post("/login", passport.authenticate("local", { session: false }), controller.login); -router.get("/profile", passport.authenticate("access-token", { session: false }), controller.profile); -router.patch("/modifyInformation", passport.authenticate("access-token", { session: false }), controller.modifyInformation); -router.patch("/modifyPassword", passport.authenticate("access-token", { session: false }), controller.modifyPassword); -router.get("/products", passport.authenticate("access-token", { session: false }), controller.products); -router.post("/refresh", passport.authenticate("refresh-token", { session: false }), controller.refreshTokens); -router.post("/logout", controller.logout); - -export default router; diff --git a/mission5_dtos/src/types/express.d.ts b/mission5_dtos/src/types/express.d.ts deleted file mode 100644 index 6f994ace7..000000000 --- a/mission5_dtos/src/types/express.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { User as PrismaUser } from "@prisma/client"; - -declare global { - namespace Express { - // Passport req.user 타입을 Prisma User로 확장 - interface User extends PrismaUser {} - } -} - -// 반드시 export {} 필요 -export {}; \ No newline at end of file diff --git a/mission5_dtos/tsconfig.json b/mission5_dtos/tsconfig.json deleted file mode 100644 index e732234c0..000000000 --- a/mission5_dtos/tsconfig.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - // Visit https://aka.ms/tsconfig to read more about this file - "compilerOptions": { - // File Layout - "rootDir": "./src", - "outDir": "./dist", - - // Environment Settings - // See also https://aka.ms/tsconfig/module - "module": "CommonJS", - "target": "ESNext", - // "types": [], - // For nodejs: - "lib": ["esnext"], - "types": ["node", "express", "passport"], - "allowJs": true, - "checkJs": true, - // and npm install -D @types/node - - // Other Outputs - "sourceMap": true, - "declaration": true, - "declarationMap": true, - - // Stricter Typechecking Options - "noUncheckedIndexedAccess": true, - "exactOptionalPropertyTypes": true, - - // Style Options - // "noImplicitReturns": true, - // "noImplicitOverride": true, - // "noUnusedLocals": true, - // "noUnusedParameters": true, - // "noFallthroughCasesInSwitch": true, - // "noPropertyAccessFromIndexSignature": true, - - // Recommended Options - "strict": true, - "jsx": "react-jsx", - "verbatimModuleSyntax": false, - "isolatedModules": true, - "noUncheckedSideEffectImports": true, - "moduleDetection": "force", - "skipLibCheck": true, - "esModuleInterop": true, - }, - "include": ["src/**/*", "src/types/**/*"] -} \ No newline at end of file From e67de47f61c99a26a9bb80349808cb8613aa2b43 Mon Sep 17 00:00:00 2001 From: Batur-s Date: Tue, 4 Nov 2025 13:38:44 +0900 Subject: [PATCH 28/38] [feat] start mission8 --- mission 8/.gitignore | 5 + mission 8/package-lock.json | 3433 +++++++++++++++++ mission 8/package.json | 51 + .../20250904083711_test/migration.sql | 94 + .../20251031084424_init/migration.sql | 14 + .../prisma/migrations/migration_lock.toml | 3 + mission 8/prisma/schema.prisma | 87 + mission 8/src/app.ts | 31 + .../src/controllers/articleController.ts | 71 + .../src/controllers/commentController.ts | 90 + mission 8/src/controllers/likeController.ts | 51 + mission 8/src/controllers/photoController.ts | 31 + .../src/controllers/productController.ts | 68 + mission 8/src/controllers/userController.ts | 96 + mission 8/src/dtos/article.dto.ts | 38 + mission 8/src/dtos/product.dto.ts | 28 + mission 8/src/dtos/user.dto.ts | 29 + mission 8/src/lib/constants.ts | 21 + mission 8/src/lib/cookieUtil.ts | 22 + mission 8/src/lib/passport/index.ts | 9 + mission 8/src/lib/passport/jwtStrategy.ts | 45 + mission 8/src/lib/passport/localStrategy.ts | 27 + mission 8/src/lib/prisma.ts | 5 + mission 8/src/lib/token.ts | 27 + mission 8/src/middlewares/errorHandler.ts | 22 + .../src/repositories/articleRepository.ts | 38 + .../src/repositories/commentRepository.ts | 50 + mission 8/src/repositories/likeRepository.ts | 67 + .../src/repositories/productRepository.ts | 49 + mission 8/src/repositories/userRepository.ts | 29 + mission 8/src/routers/articleRouter.ts | 14 + mission 8/src/routers/commentRouter.ts | 15 + mission 8/src/routers/index.ts | 19 + mission 8/src/routers/likeRouter.ts | 13 + mission 8/src/routers/photoRouter.ts | 17 + mission 8/src/routers/productRouter.ts | 14 + mission 8/src/routers/userRouter.ts | 17 + mission 8/src/services/articleService.ts | 44 + mission 8/src/services/commentService.ts | 35 + mission 8/src/services/likeService.ts | 35 + mission 8/src/services/productService.ts | 43 + mission 8/src/services/userService.ts | 48 + mission 8/src/types/express.d.ts | 11 + mission 8/tsconfig.json | 48 + 44 files changed, 5004 insertions(+) create mode 100644 mission 8/.gitignore create mode 100644 mission 8/package-lock.json create mode 100644 mission 8/package.json create mode 100644 mission 8/prisma/migrations/20250904083711_test/migration.sql create mode 100644 mission 8/prisma/migrations/20251031084424_init/migration.sql create mode 100644 mission 8/prisma/migrations/migration_lock.toml create mode 100644 mission 8/prisma/schema.prisma create mode 100644 mission 8/src/app.ts create mode 100644 mission 8/src/controllers/articleController.ts create mode 100644 mission 8/src/controllers/commentController.ts create mode 100644 mission 8/src/controllers/likeController.ts create mode 100644 mission 8/src/controllers/photoController.ts create mode 100644 mission 8/src/controllers/productController.ts create mode 100644 mission 8/src/controllers/userController.ts create mode 100644 mission 8/src/dtos/article.dto.ts create mode 100644 mission 8/src/dtos/product.dto.ts create mode 100644 mission 8/src/dtos/user.dto.ts create mode 100644 mission 8/src/lib/constants.ts create mode 100644 mission 8/src/lib/cookieUtil.ts create mode 100644 mission 8/src/lib/passport/index.ts create mode 100644 mission 8/src/lib/passport/jwtStrategy.ts create mode 100644 mission 8/src/lib/passport/localStrategy.ts create mode 100644 mission 8/src/lib/prisma.ts create mode 100644 mission 8/src/lib/token.ts create mode 100644 mission 8/src/middlewares/errorHandler.ts create mode 100644 mission 8/src/repositories/articleRepository.ts create mode 100644 mission 8/src/repositories/commentRepository.ts create mode 100644 mission 8/src/repositories/likeRepository.ts create mode 100644 mission 8/src/repositories/productRepository.ts create mode 100644 mission 8/src/repositories/userRepository.ts create mode 100644 mission 8/src/routers/articleRouter.ts create mode 100644 mission 8/src/routers/commentRouter.ts create mode 100644 mission 8/src/routers/index.ts create mode 100644 mission 8/src/routers/likeRouter.ts create mode 100644 mission 8/src/routers/photoRouter.ts create mode 100644 mission 8/src/routers/productRouter.ts create mode 100644 mission 8/src/routers/userRouter.ts create mode 100644 mission 8/src/services/articleService.ts create mode 100644 mission 8/src/services/commentService.ts create mode 100644 mission 8/src/services/likeService.ts create mode 100644 mission 8/src/services/productService.ts create mode 100644 mission 8/src/services/userService.ts create mode 100644 mission 8/src/types/express.d.ts create mode 100644 mission 8/tsconfig.json diff --git a/mission 8/.gitignore b/mission 8/.gitignore new file mode 100644 index 000000000..9f62ec0b8 --- /dev/null +++ b/mission 8/.gitignore @@ -0,0 +1,5 @@ +node_modules +# Keep environment variables out of version control +.env + +/generated/prisma diff --git a/mission 8/package-lock.json b/mission 8/package-lock.json new file mode 100644 index 000000000..006cf8369 --- /dev/null +++ b/mission 8/package-lock.json @@ -0,0 +1,3433 @@ +{ + "name": "mission3", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mission3", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@prisma/client": "^6.13.0", + "bcrypt": "^6.0.0", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^17.2.2", + "express": "^5.1.0", + "http-status": "^2.1.0", + "multer": "^2.0.2", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", + "passport-local": "^1.0.0", + "socket.io": "^4.8.1", + "tsx": "^4.20.5", + "ws": "^8.18.3", + "zod": "^4.0.14" + }, + "devDependencies": { + "@types/bcrypt": "^6.0.0", + "@types/cookie-parser": "^1.4.9", + "@types/cors": "^2.8.19", + "@types/express": "^5.0.3", + "@types/jsonwebtoken": "^9.0.10", + "@types/multer": "^2.0.0", + "@types/node": "^24.3.1", + "@types/passport": "^1.0.17", + "@types/passport-jwt": "^4.0.1", + "@types/passport-local": "^1.0.38", + "prisma": "^6.15.0", + "ts-node": "^10.9.2", + "ts-node-dev": "^2.0.0", + "typescript": "^5.9.2" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@prisma/client": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.13.0.tgz", + "integrity": "sha512-8m2+I3dQovkV8CkDMluiwEV1TxV9EXdT6xaCz39O6jYw7mkf5gwfmi+cL4LJsEPwz5tG7sreBwkRpEMJedGYUQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "prisma": "*", + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@prisma/config": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.15.0.tgz", + "integrity": "sha512-KMEoec9b2u6zX0EbSEx/dRpx1oNLjqJEBZYyK0S3TTIbZ7GEGoVyGyFRk4C72+A38cuPLbfQGQvgOD+gBErKlA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "c12": "3.1.0", + "deepmerge-ts": "7.1.5", + "effect": "3.16.12", + "empathic": "2.0.0" + } + }, + "node_modules/@prisma/debug": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.15.0.tgz", + "integrity": "sha512-y7cSeLuQmyt+A3hstAs6tsuAiVXSnw9T55ra77z0nbNkA8Lcq9rNcQg6PI00by/+WnE/aMRJ/W7sZWn2cgIy1g==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.15.0.tgz", + "integrity": "sha512-opITiR5ddFJ1N2iqa7mkRlohCZqVSsHhRcc29QXeldMljOf4FSellLT0J5goVb64EzRTKcIDeIsJBgmilNcKxA==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/fetch-engine": "6.15.0", + "@prisma/get-platform": "6.15.0" + } + }, + "node_modules/@prisma/engines-version": { + "version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb.tgz", + "integrity": "sha512-a/46aK5j6L3ePwilZYEgYDPrhBQ/n4gYjLxT5YncUTJJNRnTCVjPF86QdzUOLRdYjCLfhtZp9aum90W0J+trrg==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.15.0.tgz", + "integrity": "sha512-xcT5f6b+OWBq6vTUnRCc7qL+Im570CtwvgSj+0MTSGA1o9UDSKZ/WANvwtiRXdbYWECpyC3CukoG3A04VTAPHw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/get-platform": "6.15.0" + } + }, + "node_modules/@prisma/get-platform": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.15.0.tgz", + "integrity": "sha512-Jbb+Xbxyp05NSR1x2epabetHiXvpO8tdN2YNoWoA/ZsbYyxxu/CO/ROBauIFuMXs3Ti+W7N7SJtWsHGaWte9Rg==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-/oJGukuH3D2+D+3H4JWLaAsJ/ji86dhRidzZ/Od7H/i8g+aCmvkeCc6Ni/f9uxGLSQVCRZkX2/lqEFG2BvWtlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie-parser": { + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.9.tgz", + "integrity": "sha512-tGZiZ2Gtc4m3wIdLkZ8mkj1T6CEHb35+VApbL2T14Dew8HA7c+04dmKqsKRNC+8RJPm16JEK0tFSwdZqubfc4g==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz", + "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", + "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/multer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz", + "integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/node": { + "version": "24.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz", + "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~7.10.0" + } + }, + "node_modules/@types/passport": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", + "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/passport-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-Y0Ykz6nWP4jpxgEUYq8NoVZeCQPo1ZndJLfapI249g1jHChvRfZRO/LS3tqu26YgAS/laI1qx98sYGz0IalRXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/jsonwebtoken": "*", + "@types/passport-strategy": "*" + } + }, + "node_modules/@types/passport-local": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.38.tgz", + "integrity": "sha512-nsrW4A963lYE7lNTv9cr5WmiUD1ibYJvWrpE13oxApFsRt77b0RdtZvKbCdNIY4v/QZ6TRQWaDDEwV1kCTmcXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-strategy": "*" + } + }, + "node_modules/@types/passport-strategy": { + "version": "0.2.38", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", + "integrity": "sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", + "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.8", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", + "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/strip-json-comments": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", + "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "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==", + "license": "MIT" + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.0", + "node-gyp-build": "^4.8.4" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "BSD-3-Clause" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/c12": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", + "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.3", + "confbox": "^0.2.2", + "defu": "^6.1.4", + "dotenv": "^16.6.1", + "exsolve": "^1.0.7", + "giget": "^2.0.0", + "jiti": "^2.4.2", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^1.0.0", + "pkg-types": "^2.2.0", + "rc9": "^2.1.2" + }, + "peerDependencies": { + "magicast": "^0.3.5" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } + } + }, + "node_modules/c12/node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "devOptional": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "consola": "^3.2.3" + } + }, + "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, + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "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, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deepmerge-ts": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", + "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dotenv": { + "version": "17.2.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", + "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/dynamic-dedupe": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", + "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + } + }, + "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==", + "license": "Apache-2.0", + "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", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/effect": { + "version": "3.16.12", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.16.12.tgz", + "integrity": "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "fast-check": "^3.23.1" + } + }, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/engine.io": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", + "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", + "license": "MIT", + "dependencies": { + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.7.2", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/fast-check": { + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", + "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "dependencies": { + "pure-rand": "^6.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/giget": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", + "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.0", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.6", + "nypm": "^0.6.0", + "pathe": "^2.0.3" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "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/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, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-status": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-status/-/http-status-2.1.0.tgz", + "integrity": "sha512-O5kPr7AW7wYd/BBiOezTwnVAnmSNFY+J7hlZD2X5IOxVBetjcHAiTXhzj0gMrnojQlwy+UT1/Y3H3vJ3UlmvLA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 0.4.0" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "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==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/jiti": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", + "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "devOptional": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", + "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.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "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, + "license": "ISC" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.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, + "license": "ISC", + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/multer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", + "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", + "object-assign": "^4.1.1", + "type-is": "^1.6.18", + "xtend": "^4.0.2" + }, + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/multer/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-addon-api": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz", + "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nypm": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.1.tgz", + "integrity": "sha512-hlacBiRiv1k9hZFiphPUkfSQ/ZfQzZDzC+8z0wL3lvDAOUu/2NnChkKuMoMjNur/9OpKuz2QsIeiPVN0xM5Q0w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.2", + "pathe": "^2.0.3", + "pkg-types": "^2.2.0", + "tinyexec": "^1.0.1" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "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==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "license": "MIT", + "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-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", + "license": "MIT", + "dependencies": { + "jsonwebtoken": "^9.0.0", + "passport-strategy": "^1.0.0" + } + }, + "node_modules/passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "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-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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, + "node_modules/prisma": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.15.0.tgz", + "integrity": "sha512-E6RCgOt+kUVtjtZgLQDBJ6md2tDItLJNExwI0XJeBc1FKL+Vwb+ovxXxuok9r8oBgsOXBA33fGDuE/0qDdCWqQ==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@prisma/config": "6.15.0", + "@prisma/engines": "6.15.0" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc9": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", + "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "defu": "^6.1.4", + "destr": "^2.0.3" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "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" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/socket.io": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.6.0", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "license": "MIT", + "dependencies": { + "debug": "~4.3.4", + "ws": "~8.17.1" + } + }, + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-adapter/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/socket.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/socket.io/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/socket.io/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tinyexec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", + "devOptional": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "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/ts-node-dev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz", + "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.1", + "dynamic-dedupe": "^0.3.0", + "minimist": "^1.2.6", + "mkdirp": "^1.0.4", + "resolve": "^1.0.0", + "rimraf": "^2.6.1", + "source-map-support": "^0.5.12", + "tree-kill": "^1.2.2", + "ts-node": "^10.4.0", + "tsconfig": "^7.0.0" + }, + "bin": { + "ts-node-dev": "lib/bin.js", + "tsnd": "lib/bin.js" + }, + "engines": { + "node": ">=0.8.0" + }, + "peerDependencies": { + "node-notifier": "*", + "typescript": "*" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/ts-node-dev/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "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" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/ts-node-dev/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-node-dev/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/tsconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", + "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/strip-bom": "^3.0.0", + "@types/strip-json-comments": "0.0.30", + "strip-bom": "^3.0.0", + "strip-json-comments": "^2.0.0" + } + }, + "node_modules/tsx": { + "version": "4.20.5", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.5.tgz", + "integrity": "sha512-+wKjMNU9w/EaQayHXb7WA7ZaHY6hN8WgfvHNQ3t1PnU91/7O8TcTnIhCDYTZwnt8JsO9IBqZ30Ln1r7pPF52Aw==", + "license": "MIT", + "dependencies": { + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "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==", + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "devOptional": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/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, + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": 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==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/zod": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.0.14.tgz", + "integrity": "sha512-nGFJTnJN6cM2v9kXL+SOBq3AtjQby3Mv5ySGFof5UGRHrRioSJ5iG680cYNjE/yWk671nROcpPj4hAS8nyLhSw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/mission 8/package.json b/mission 8/package.json new file mode 100644 index 000000000..1bf13be55 --- /dev/null +++ b/mission 8/package.json @@ -0,0 +1,51 @@ +{ + "name": "mission3", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "dev": "ts-node --files src/app.ts", + "start": "node dist/app.js", + "lint": "eslint . --ext .ts", + "prisma:generate": "prisma generate", + "prisma:migrate": "prisma migrate dev" + }, + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "@prisma/client": "^6.13.0", + "bcrypt": "^6.0.0", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^17.2.2", + "express": "^5.1.0", + "http-status": "^2.1.0", + "multer": "^2.0.2", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", + "passport-local": "^1.0.0", + "socket.io": "^4.8.1", + "tsx": "^4.20.5", + "ws": "^8.18.3", + "zod": "^4.0.14" + }, + "devDependencies": { + "@types/bcrypt": "^6.0.0", + "@types/cookie-parser": "^1.4.9", + "@types/cors": "^2.8.19", + "@types/express": "^5.0.3", + "@types/jsonwebtoken": "^9.0.10", + "@types/multer": "^2.0.0", + "@types/node": "^24.3.1", + "@types/passport": "^1.0.17", + "@types/passport-jwt": "^4.0.1", + "@types/passport-local": "^1.0.38", + "prisma": "^6.15.0", + "ts-node": "^10.9.2", + "ts-node-dev": "^2.0.0", + "typescript": "^5.9.2" + }, + "prisma": { + "seed": "node prisma/seed.js" + } +} diff --git a/mission 8/prisma/migrations/20250904083711_test/migration.sql b/mission 8/prisma/migrations/20250904083711_test/migration.sql new file mode 100644 index 000000000..ad7fbdc5d --- /dev/null +++ b/mission 8/prisma/migrations/20250904083711_test/migration.sql @@ -0,0 +1,94 @@ +-- CreateTable +CREATE TABLE "public"."User" ( + "id" SERIAL NOT NULL, + "email" TEXT NOT NULL, + "nickname" TEXT NOT NULL, + "image" TEXT, + "password" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Product" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT NOT NULL, + "price" INTEGER NOT NULL, + "tags" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Product_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Article" ( + "id" SERIAL NOT NULL, + "title" TEXT NOT NULL, + "content" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Article_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Comment" ( + "id" SERIAL NOT NULL, + "content" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "productId" INTEGER, + "articleId" INTEGER, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Comment_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Like" ( + "id" SERIAL NOT NULL, + "like" BOOLEAN NOT NULL DEFAULT true, + "userId" INTEGER NOT NULL, + "productId" INTEGER, + "articleId" INTEGER, + + CONSTRAINT "Like_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "public"."User"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "Like_userId_productId_key" ON "public"."Like"("userId", "productId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Like_userId_articleId_key" ON "public"."Like"("userId", "articleId"); + +-- AddForeignKey +ALTER TABLE "public"."Product" ADD CONSTRAINT "Product_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Article" ADD CONSTRAINT "Article_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_productId_fkey" FOREIGN KEY ("productId") REFERENCES "public"."Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "public"."Article"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_productId_fkey" FOREIGN KEY ("productId") REFERENCES "public"."Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "public"."Article"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/mission 8/prisma/migrations/20251031084424_init/migration.sql b/mission 8/prisma/migrations/20251031084424_init/migration.sql new file mode 100644 index 000000000..2827ddec8 --- /dev/null +++ b/mission 8/prisma/migrations/20251031084424_init/migration.sql @@ -0,0 +1,14 @@ +-- CreateTable +CREATE TABLE "public"."Alert" ( + "id" SERIAL NOT NULL, + "userId" INTEGER NOT NULL, + "message" TEXT NOT NULL, + "link" TEXT, + "isRead" BOOLEAN NOT NULL DEFAULT false, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Alert_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "public"."Alert" ADD CONSTRAINT "Alert_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/mission 8/prisma/migrations/migration_lock.toml b/mission 8/prisma/migrations/migration_lock.toml new file mode 100644 index 000000000..044d57cdb --- /dev/null +++ b/mission 8/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (e.g., Git) +provider = "postgresql" diff --git a/mission 8/prisma/schema.prisma b/mission 8/prisma/schema.prisma new file mode 100644 index 000000000..a43c08252 --- /dev/null +++ b/mission 8/prisma/schema.prisma @@ -0,0 +1,87 @@ +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" +} + +model User { + id Int @id @default(autoincrement()) + email String @unique + nickname String + image String? + password String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + article Article[] + product Product[] + comment Comment[] + like Like[] + alert Alert[] +} + +model Product { + id Int @id @default(autoincrement()) + name String + description String + price Int + tags String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + comment Comment[] + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + like Like[] +} + +model Article { + id Int @id @default(autoincrement()) + title String + content String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + comment Comment[] + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + like Like[] +} + +model Comment { + id Int @id @default(autoincrement()) + content String + createdAt DateTime @default(now()) + productId Int? + product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) + articleId Int? + article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) +} + +model Like { + id Int @id @default(autoincrement()) + like Boolean @default(true) + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + productId Int? + product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) + articleId Int? + article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) + + // 유저-상품, 유저-게시글 각각 중복 방지, 좋아요 중첩 방지 + @@unique([userId, productId]) + @@unique([userId, articleId]) +} + +model Alert { + id Int @id @default(autoincrement()) + userId Int + message String + link String? + isRead Boolean @default(false) + createdAt DateTime @default(now()) + + user User @relation(fields: [userId], references: [id]) +} \ No newline at end of file diff --git a/mission 8/src/app.ts b/mission 8/src/app.ts new file mode 100644 index 000000000..9be0a16ce --- /dev/null +++ b/mission 8/src/app.ts @@ -0,0 +1,31 @@ +import express from "express"; +import cookieParser from "cookie-parser"; +import router from "./routers/index"; +import { PORT } from "./lib/constants"; +import passport from "./lib/passport/index"; +import cors from "cors"; +import { errorHandler } from "./middlewares/errorHandler"; + +const app = express(); + +app.use(express.urlencoded({ extended: true })); + +app.use(express.json()); +app.use(cookieParser()); +const corsOptions = { + //CORS 설정 및 whitelist로 'http://localhost:3000'을 설정 + origin: "http://localhost:3000", + optionSuccessStatus: 200, +}; + +app.use(cors(corsOptions)); +app.use(passport.initialize()); +app.use(router); +app.use("/download", express.static("uploads")); + + +app.use(errorHandler); + +app.listen(PORT, () => { + console.log(`Server is running on http://localhost:${PORT}`); +}); diff --git a/mission 8/src/controllers/articleController.ts b/mission 8/src/controllers/articleController.ts new file mode 100644 index 000000000..250dac6e8 --- /dev/null +++ b/mission 8/src/controllers/articleController.ts @@ -0,0 +1,71 @@ +import { Request, Response, NextFunction } from "express"; +import status from "http-status"; +import { ArticleService } from "../services/articleService"; +import { ArticleCreateSchema, ArticleUpdateSchema, ArticleQuerySchema, ArticleUpdateDTO } from "../dtos/article.dto"; + +const articleService = new ArticleService(); + +export class ArticleController { + async create(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const parsed = ArticleCreateSchema.parse(req.body); + const article = await articleService.create(req.user.id, parsed); + res.status(status.CREATED).json(article); + } catch (err) { + next(err); + } + } + + async list(req: Request, res: Response, next: NextFunction) { + try { + const parsed = ArticleQuerySchema.parse(req.query); + const articles = await articleService.list(parsed); + res.status(status.OK).json(articles); + } catch (err) { + next(err); + } + } + + async detail(req: Request, res: Response, next: NextFunction) { + try { + const articleId = Number(req.params.id); + const article = await articleService.getDetail(articleId); + if (!article) return res.status(status.NOT_FOUND).json({ message: "Article not found" }); + res.status(status.OK).json(article); + } catch (err) { + next(err); + } + } + + async update(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const parsed = ArticleUpdateSchema.parse(req.body) as { title?: string; content?: string; }; + const articleId = Number(req.params.id); + const updated = await articleService.update(req.user.id, articleId, parsed); + + res.status(status.OK).json(updated); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + + async delete(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const articleId = Number(req.params.id); + await articleService.delete(req.user.id, articleId); + res.status(status.NO_CONTENT).end(); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } +} diff --git a/mission 8/src/controllers/commentController.ts b/mission 8/src/controllers/commentController.ts new file mode 100644 index 000000000..652dd54f7 --- /dev/null +++ b/mission 8/src/controllers/commentController.ts @@ -0,0 +1,90 @@ +import { Request, Response, NextFunction } from "express"; +import { z } from "zod"; +import status from "http-status"; +import { CommentService } from "../services/commentService"; + +const commentService = new CommentService(); + +// body 검증 +const commentSchema = z.object({ + content: z.string().min(5).max(100), +}); + +// query 검증 +const commentListSchema = z.object({ + id: z.coerce.number().int().positive(), + lastId: z.coerce.number().int().positive().optional(), +}); + +export class CommentController { + async createProductComment(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const productId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const comment = await commentService.createProductComment(req.user.id, productId, parsed.content); + res.status(status.CREATED).json(comment); + } catch (err) { + next(err); + } + } + + async createArticleComment(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const articleId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const comment = await commentService.createArticleComment(req.user.id, articleId, parsed.content); + res.status(status.CREATED).json(comment); + } catch (err) { + next(err); + } + } + + async modifyComment(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const commentId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const updated = await commentService.updateComment(req.user.id, commentId, parsed.content); + res.status(status.OK).json(updated); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Comment not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + + async deleteComment(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const commentId = Number(req.params.id); + await commentService.deleteComment(req.user.id, commentId); + res.status(status.NO_CONTENT).end(); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Comment not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + + async productCommentList(req: Request, res: Response, next: NextFunction) { + try { + const parsed = commentListSchema.parse({ id: req.params.id, lastId: req.query.lastId }); + const comments = await commentService.getProductComments(parsed.id, parsed.lastId); + res.status(status.OK).json(comments); + } catch (err) { + next(err); + } + } + + async articleCommentList(req: Request, res: Response, next: NextFunction) { + try { + const parsed = commentListSchema.parse({ id: req.params.id, lastId: req.query.lastId }); + const comments = await commentService.getArticleComments(parsed.id, parsed.lastId); + res.status(status.OK).json(comments); + } catch (err) { + next(err); + } + } +} \ No newline at end of file diff --git a/mission 8/src/controllers/likeController.ts b/mission 8/src/controllers/likeController.ts new file mode 100644 index 000000000..5e4c1edba --- /dev/null +++ b/mission 8/src/controllers/likeController.ts @@ -0,0 +1,51 @@ +import { Request, Response, NextFunction } from "express"; +import status from "http-status"; +import { LikeService } from "../services/likeService"; + +const likeService = new LikeService(); + +export class LikeController { + async likeArticle(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const result = await likeService.likeArticle(req.user.id, Number(req.params.id)); + res.status(status.OK).json({ message: "Like toggled", isLiked: result.like }); + } catch (err: any) { + if (err.message === "ARTICLE_NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" }); + next(err); + } + } + + async likeProduct(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const result = await likeService.likeProduct(req.user.id, Number(req.params.id)); + res.status(status.OK).json({ message: "Like toggled", isLiked: result.like }); + } catch (err: any) { + if (err.message === "PRODUCT_NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + next(err); + } + } + + async getLikedArticles(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const likedArticles = await likeService.getLikedArticles(req.user.id); + const articles = likedArticles.map((l) => ({ ...l.article, isLiked: true })); + res.status(status.OK).json(articles); + } catch (err) { + next(err); + } + } + + async getLikedProducts(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const likedProducts = await likeService.getLikedProducts(req.user.id); + const products = likedProducts.map((l) => ({ ...l.product, isLiked: true })); + res.status(status.OK).json(products); + } catch (err) { + next(err); + } + } +} \ No newline at end of file diff --git a/mission 8/src/controllers/photoController.ts b/mission 8/src/controllers/photoController.ts new file mode 100644 index 000000000..0f52730ae --- /dev/null +++ b/mission 8/src/controllers/photoController.ts @@ -0,0 +1,31 @@ +import { Request, Response, NextFunction } from "express"; +import prisma from "../lib/prisma"; +import status from "http-status"; + +export class PhotoController { + async upload(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + + if (!req.file) { + return res.status(status.BAD_REQUEST).json({ message: "No file uploaded" }); + } + + try { + // 파일 저장 위치 → 지금은 로컬, 나중에 S3 같은 외부 스토리지로 확장 가능 + const imageUrl = `/download/${req.file.filename}`; + + // 📌 기본 동작: 유저 프로필 업데이트 + const updatedUser = await prisma.user.update({ + where: { id: req.user.id }, + data: { image: imageUrl }, + }); + + res.status(status.OK).json({ + message: "Photo uploaded successfully", + image: updatedUser.image, + }); + } catch (err) { + next(err); + } + } +} \ No newline at end of file diff --git a/mission 8/src/controllers/productController.ts b/mission 8/src/controllers/productController.ts new file mode 100644 index 000000000..5d42d09b9 --- /dev/null +++ b/mission 8/src/controllers/productController.ts @@ -0,0 +1,68 @@ +import { Request, Response, NextFunction } from "express"; +import status from "http-status"; +import { ProductService } from "../services/productService"; +import { ProductCreateSchema, ProductUpdateSchema, ProductQuerySchema } from "../dtos/product.dto"; + +const productService = new ProductService(); + +export class ProductController { + async create(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = ProductCreateSchema.parse(req.body); + const product = await productService.create(req.user.id, parsed); + res.status(status.CREATED).json(product); + } catch (err) { + next(err); + } + } + + async list(req: Request, res: Response, next: NextFunction) { + try { + const parsed = ProductQuerySchema.parse(req.query); + const products = await productService.list(parsed); + res.status(status.OK).json(products); + } catch (err) { + next(err); + } + } + + async detail(req: Request, res: Response, next: NextFunction) { + try { + const productId = Number(req.params.id); + const product = await productService.getDetail(productId); + if (!product) return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + res.status(status.OK).json(product); + } catch (err) { + next(err); + } + } + + async update(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = ProductUpdateSchema.parse(req.body) as { name?: string; description?: string; price?: number; tags?: string; }; + const productId = Number(req.params.id); + const updated = await productService.update(req.user.id, productId, parsed); + + res.status(status.OK).json(updated); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + + async delete(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const productId = Number(req.params.id); + await productService.delete(req.user.id, productId); + res.status(status.NO_CONTENT).end(); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } +} \ No newline at end of file diff --git a/mission 8/src/controllers/userController.ts b/mission 8/src/controllers/userController.ts new file mode 100644 index 000000000..8f706c6b5 --- /dev/null +++ b/mission 8/src/controllers/userController.ts @@ -0,0 +1,96 @@ +import { Request, Response, NextFunction } from "express"; +import status from "http-status"; +import { UserService } from "../services/userService"; +import { setTokenCookies, clearTokenCookies } from "../lib/cookieUtil"; +import { UserRegisterSchema, UserUpdateSchema, UserPasswordSchema, UserLoginSchema } from "../dtos/user.dto"; + +const userService = new UserService(); + +export class UserController { + async register(req: Request, res: Response, next: NextFunction) { + try { + const parsed = UserRegisterSchema.parse(req.body); + const result = await userService.register(parsed); + res.status(status.CREATED).json(result); + } catch (err: any) { + if (err.message === "EMAIL_EXISTS") { + return res.status(status.CONFLICT).json({ message: "This ID already exists" }); + } + next(err); + } + } + + login(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + try { + const { accessToken, refreshToken } = userService.generateUserTokens(req.user.id); + setTokenCookies(res, accessToken, refreshToken); + res.status(status.OK).json({ token: accessToken, refreshToken }); + } catch (err) { + next(err); + } + } + + async profile(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const profile = await userService.getProfile(req.user.id); + res.status(status.OK).json(profile); + } catch (err) { + next(err); + } + } + + async modifyInformation(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const parsed = UserUpdateSchema.parse(req.body); // DTO 검증 + const updatedUser = await userService.updateInformation(req.user.id, parsed.nickname, parsed.image); + + res.status(status.OK).json({ message: "User information updated successfully", user: updatedUser }); + } catch (err: any) { + if (err.message === "NO_DATA") return res.status(status.BAD_REQUEST).json({ message: "No update data provided" }); + next(err); + } + } + + async modifyPassword(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const parsed = UserPasswordSchema.parse(req.body); // DTO 검증 + const result = await userService.updatePassword(req.user.id, parsed); + + res.status(status.OK).json(result); + } catch (err) { + next(err); + } + } + + async products(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const products = await userService.getProducts(req.user.id); + if (!products || products.length === 0) { + return res.status(status.NOT_FOUND).json({ message: "No product" }); + } + res.status(status.OK).json(products); + } catch (err) { + next(err); + } + } + + refreshTokens(req: Request, res: Response) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const { accessToken, refreshToken } = userService.generateUserTokens(req.user.id); + setTokenCookies(res, accessToken, refreshToken); + res.status(status.OK).send({ message: "Tokens refreshed" }); + } + + logout(req: Request, res: Response) { + clearTokenCookies(res); + res.status(status.OK).send({ message: "Logged out successfully" }); + } +} diff --git a/mission 8/src/dtos/article.dto.ts b/mission 8/src/dtos/article.dto.ts new file mode 100644 index 000000000..c6709cf00 --- /dev/null +++ b/mission 8/src/dtos/article.dto.ts @@ -0,0 +1,38 @@ +import { z } from "zod"; + +// CREATE DTO +export const ArticleCreateSchema = z.object({ + title: z.string().min(1, { message: "제목을 입력해주세요" }), + content: z + .string() + .min(10, { message: "내용은 최소 10자 이상이어야 합니다." }) + .max(200, { message: "내용은 최대 200자까지 가능합니다." }), +}); +export type ArticleCreateDTO = z.infer; + +// UPDATE DTO (PATCH) +export const ArticleUpdateSchema = z.object({ + title: z.string().min(1, { message: "제목을 입력해주세요" }).optional(), + content: z + .string() + .min(10, { message: "내용은 최소 10자 이상이어야 합니다." }) + .max(200, { message: "내용은 최대 200자까지 가능합니다." }) + .optional(), +}); +export type ArticleUpdateDTO = z.infer; + +// QUERY DTO (GET /articles) +export const ArticleQuerySchema = z.object({ + page: z + .string() + .default("1") + .transform(Number) + .refine((val) => val > 0, { message: "page는 1 이상의 정수여야 합니다." }), + pageSize: z + .string() + .default("5") + .transform(Number) + .refine((val) => val > 0 && val <= 100, { message: "pageSize는 1~100 사이여야 합니다." }), + keyword: z.string().default(""), +}); +export type ArticleQueryDTO = z.infer; diff --git a/mission 8/src/dtos/product.dto.ts b/mission 8/src/dtos/product.dto.ts new file mode 100644 index 000000000..edac3858a --- /dev/null +++ b/mission 8/src/dtos/product.dto.ts @@ -0,0 +1,28 @@ +import { z } from "zod"; + + +// CREATE DTO +export const ProductCreateSchema = z.object({ + name: z.string().min(1, { message: "이름을 입력해주세요" }), + description: z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }), + price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }), + tags: z.string().default(""), +}); +export type ProductCreateDTO = z.infer; + +// UPDATE DTO +export const ProductUpdateSchema = z.object({ + name: z.string().min(1, { message: "이름을 입력해주세요" }).optional(), + description: z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }).optional(), + price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }).optional(), + tags: z.string().default("").optional(), +}); +export type ProductUpdateDTO = z.infer; + +// QUERY DTO +export const ProductQuerySchema = z.object({ + page: z.string().default("1").transform(Number).refine((v) => v > 0), + pageSize: z.string().default("5").transform(Number).refine((v) => v > 0 && v <= 100), + keyword: z.string().default(""), +}); +export type ProductQueryDTO = z.infer; \ No newline at end of file diff --git a/mission 8/src/dtos/user.dto.ts b/mission 8/src/dtos/user.dto.ts new file mode 100644 index 000000000..1bed9d74a --- /dev/null +++ b/mission 8/src/dtos/user.dto.ts @@ -0,0 +1,29 @@ +import { z } from "zod"; + +// 회원가입 +export const UserRegisterSchema = z.object({ + email: z.string().email({ message: "Invalid email" }), + nickname: z.string().min(2, { message: "Nickname too short" }), + password: z.string().min(6, { message: "Password too short" }), +}); +export type UserRegisterDTO = z.infer; + +// 로그인 +export const UserLoginSchema = z.object({ + email: z.string().email(), + password: z.string().min(6), +}); +export type UserLoginDTO = z.infer; + +// 정보 수정 (PATCH) +export const UserUpdateSchema = z.object({ + nickname: z.string().min(2).optional(), + image: z.string().url().optional(), +}); +export type UserUpdateDTO = z.infer; + +// 비밀번호 수정 +export const UserPasswordSchema = z.object({ + password: z.string().min(6, { message: "Password too short" }), +}); +export type UserPasswordDTO = z.infer; diff --git a/mission 8/src/lib/constants.ts b/mission 8/src/lib/constants.ts new file mode 100644 index 000000000..af8e48a99 --- /dev/null +++ b/mission 8/src/lib/constants.ts @@ -0,0 +1,21 @@ +import dotenv from 'dotenv'; + +dotenv.config(); + +const NODE_ENV = process.env.NODE_ENV || 'development'; +const PORT = process.env.PORT || 3000; +const JWT_ACCESS_TOKEN_SECRET = + process.env.JWT_ACCESS_TOKEN_SECRET || 'your_jwt_access_token_secret'; +const JWT_REFRESH_TOKEN_SECRET = + process.env.JWT_REFRESH_TOKEN_SECRET || 'your_jwt_refresh_token_secret'; +const ACCESS_TOKEN_COOKIE_NAME = 'access-token'; +const REFRESH_TOKEN_COOKIE_NAME = 'refresh-token'; + +export { + NODE_ENV, + PORT, + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, + ACCESS_TOKEN_COOKIE_NAME, + REFRESH_TOKEN_COOKIE_NAME, +}; diff --git a/mission 8/src/lib/cookieUtil.ts b/mission 8/src/lib/cookieUtil.ts new file mode 100644 index 000000000..6d50ff83d --- /dev/null +++ b/mission 8/src/lib/cookieUtil.ts @@ -0,0 +1,22 @@ +import { Response } from "express"; +import { ACCESS_TOKEN_COOKIE_NAME, REFRESH_TOKEN_COOKIE_NAME, NODE_ENV } from "./constants"; + +export function setTokenCookies(res: Response, accessToken: string, refreshToken: string) { + res.cookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, { + httpOnly: true, + secure: NODE_ENV === "production", + maxAge: 1 * 60 * 60 * 1000, // 1시간 + }); + + res.cookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken, { + httpOnly: true, + secure: NODE_ENV === "production", + maxAge: 7 * 24 * 60 * 60 * 1000, // 7일 + path: "/users/refresh", + }); +} + +export function clearTokenCookies(res: Response) { + res.clearCookie(ACCESS_TOKEN_COOKIE_NAME); + res.clearCookie(REFRESH_TOKEN_COOKIE_NAME); +} diff --git a/mission 8/src/lib/passport/index.ts b/mission 8/src/lib/passport/index.ts new file mode 100644 index 000000000..771eb1518 --- /dev/null +++ b/mission 8/src/lib/passport/index.ts @@ -0,0 +1,9 @@ +import passport from 'passport'; +import { localStrategy } from './localStrategy'; +import { accessTokenStrategy, refreshTokenStrategy } from './jwtStrategy'; + +passport.use('local', localStrategy); +passport.use('access-token', accessTokenStrategy); +passport.use('refresh-token', refreshTokenStrategy); + +export default passport; diff --git a/mission 8/src/lib/passport/jwtStrategy.ts b/mission 8/src/lib/passport/jwtStrategy.ts new file mode 100644 index 000000000..7d258318c --- /dev/null +++ b/mission 8/src/lib/passport/jwtStrategy.ts @@ -0,0 +1,45 @@ +import { Strategy as JwtStrategy } from 'passport-jwt'; +import prisma from '../prisma'; +import type { Request } from 'express'; +import type { VerifiedCallback } from 'passport-jwt'; +import { + ACCESS_TOKEN_COOKIE_NAME, + REFRESH_TOKEN_COOKIE_NAME, + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, +} from '../constants'; + +interface JwtPayload { + sub: number; +} + +const accessTokenOptions = { + jwtFromRequest: (req: Request) => req.cookies[ACCESS_TOKEN_COOKIE_NAME], + secretOrKey: JWT_ACCESS_TOKEN_SECRET, +}; + +const refreshTokenOptions = { + jwtFromRequest: (req: Request) => req.cookies[REFRESH_TOKEN_COOKIE_NAME], + secretOrKey: JWT_REFRESH_TOKEN_SECRET, +}; + +async function jwtVerify(payload: JwtPayload, done: VerifiedCallback) { + try { + const user = await prisma.user.findUnique({ + where: { id: payload.sub }, + }); + done(null, user); + } catch (error) { + done(error, false); + } +} + +export const accessTokenStrategy = new JwtStrategy( + accessTokenOptions, + jwtVerify +); + +export const refreshTokenStrategy = new JwtStrategy( + refreshTokenOptions, + jwtVerify +); diff --git a/mission 8/src/lib/passport/localStrategy.ts b/mission 8/src/lib/passport/localStrategy.ts new file mode 100644 index 000000000..3c3e7ba10 --- /dev/null +++ b/mission 8/src/lib/passport/localStrategy.ts @@ -0,0 +1,27 @@ +import { Strategy as LocalStrategy } from "passport-local"; +import bcrypt from "bcrypt"; +import prisma from "../prisma"; + +export const localStrategy = new LocalStrategy( + { + usernameField: "email", // email을 localStrategy의 고정값 'username' 대신 쓰도록 지정 + passwordField: "password", + }, + async (email, password, done) => { + try { + const user = await prisma.user.findUnique({ where: { email } }); + if (!user) { + return done(null, false, { message: "No user found" }); + } + + const isPasswordValid = await bcrypt.compare(password, user.password); + if (!isPasswordValid) { + return done(null, false, { message: "Invalid password" }); + } + + return done(null, user); + } catch (err) { + return done(err); + } + } +); diff --git a/mission 8/src/lib/prisma.ts b/mission 8/src/lib/prisma.ts new file mode 100644 index 000000000..b904402d2 --- /dev/null +++ b/mission 8/src/lib/prisma.ts @@ -0,0 +1,5 @@ +import { PrismaClient } from '@prisma/client'; + +const prisma = new PrismaClient(); + +export default prisma; \ No newline at end of file diff --git a/mission 8/src/lib/token.ts b/mission 8/src/lib/token.ts new file mode 100644 index 000000000..79a05e281 --- /dev/null +++ b/mission 8/src/lib/token.ts @@ -0,0 +1,27 @@ +import jwt from 'jsonwebtoken'; +import { + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, +} from './constants'; + +function generateTokens(userId: number) { + const accessToken = jwt.sign({ sub: userId }, JWT_ACCESS_TOKEN_SECRET, { + expiresIn: '1h', + }); + const refreshToken = jwt.sign({ sub: userId }, JWT_REFRESH_TOKEN_SECRET, { + expiresIn: '1d', + }); + return { accessToken, refreshToken }; +} + +function verifyAccessToken(token: string) { + const decoded = jwt.verify(token, JWT_ACCESS_TOKEN_SECRET); + return { userId: decoded.sub }; +} + +function verifyRefreshToken(token: string) { + const decoded = jwt.verify(token, JWT_REFRESH_TOKEN_SECRET); + return { userId: decoded.sub }; +} + +export { generateTokens, verifyAccessToken, verifyRefreshToken }; diff --git a/mission 8/src/middlewares/errorHandler.ts b/mission 8/src/middlewares/errorHandler.ts new file mode 100644 index 000000000..dcaa5aaf3 --- /dev/null +++ b/mission 8/src/middlewares/errorHandler.ts @@ -0,0 +1,22 @@ +import { z } from "zod"; +import httpStatus from "http-status"; +import express , { type Request, type Response, type NextFunction } from "express"; + +interface ExtendedError extends Error { + code?: string; +} + +export function errorHandler(err: ExtendedError, req: Request, res: Response, next: NextFunction) { + if (err instanceof z.ZodError) { + return res.status(httpStatus.BAD_REQUEST).json({ error: err.issues }); + } + + if (err.code === "P2025") { + return res.status(httpStatus.NOT_FOUND).json({ error: "Record not found" }); + } + + console.error("unhandled Error:", err); + return res + .status(httpStatus.INTERNAL_SERVER_ERROR) + .json({ error: "Internal Server Error" }); +} diff --git a/mission 8/src/repositories/articleRepository.ts b/mission 8/src/repositories/articleRepository.ts new file mode 100644 index 000000000..07318b163 --- /dev/null +++ b/mission 8/src/repositories/articleRepository.ts @@ -0,0 +1,38 @@ +import prisma from "../lib/prisma"; +import { Prisma } from "@prisma/client"; + +export class ArticleRepository { + async createArticle(data: { userId: number; title: string; content: string }) { + return prisma.article.create({ data }); + } + + async findMany(where: Prisma.ArticleWhereInput, skip: number, take: number) { + return prisma.article.findMany({ + skip, + take, + orderBy: { createdAt: "desc" }, + select: { id: true, title: true, content: true, createdAt: true }, + where, + }); + } + + async findById(id: number) { + return prisma.article.findUnique({ + where: { id }, + select: { id: true, userId: true, title: true, content: true, createdAt: true }, + }); + } + + async updatedArticle(id: number, data: { title?: string; content?: string }) { + // undefined 필드 제거 + const updateData: { title?: string; content?: string } = {}; + if (data.title !== undefined) updateData.title = data.title; + if (data.content !== undefined) updateData.content = data.content; + + return prisma.article.update({ where: { id }, data: updateData }); + } + + async deleteArticle(id: number) { + return prisma.article.delete({ where: { id } }); + } +} diff --git a/mission 8/src/repositories/commentRepository.ts b/mission 8/src/repositories/commentRepository.ts new file mode 100644 index 000000000..028695d4a --- /dev/null +++ b/mission 8/src/repositories/commentRepository.ts @@ -0,0 +1,50 @@ +import prisma from "../lib/prisma"; + +export class CommentRepository { + async createProductComment(userId: number, productId: number, content: string) { + return prisma.comment.create({ + data: { content, productId, articleId: null, userId }, + }); + } + + async createArticleComment(userId: number, articleId: number, content: string) { + return prisma.comment.create({ + data: { content, productId: null, articleId, userId }, + }); + } + + async findById(commentId: number) { + return prisma.comment.findUnique({ where: { id: commentId } }); + } + + async updateComment(commentId: number, content: string) { + return prisma.comment.update({ + where: { id: commentId }, + data: { content }, + }); + } + + async deleteComment(commentId: number) { + return prisma.comment.delete({ where: { id: commentId } }); + } + + async findProductComments(productId: number, lastId?: number) { + return prisma.comment.findMany({ + where: { articleId: null, productId }, + take: 5, + skip: lastId ? 1 : 0, + ...(lastId && { cursor: { id: lastId } }), + select: { id: true, content: true, createdAt: true }, + }); + } + + async findArticleComments(articleId: number, lastId?: number) { + return prisma.comment.findMany({ + where: { articleId, productId: null }, + take: 5, + skip: lastId ? 1 : 0, + ...(lastId && { cursor: { id: lastId } }), + select: { id: true, content: true, createdAt: true }, + }); + } +} \ No newline at end of file diff --git a/mission 8/src/repositories/likeRepository.ts b/mission 8/src/repositories/likeRepository.ts new file mode 100644 index 000000000..f2b154b8f --- /dev/null +++ b/mission 8/src/repositories/likeRepository.ts @@ -0,0 +1,67 @@ +import prisma from "../lib/prisma"; + +export class LikeRepository { + async findArticle(articleId: number) { + return prisma.article.findUnique({ where: { id: articleId } }); + } + + async findProduct(productId: number) { + return prisma.product.findUnique({ where: { id: productId } }); + } + + async findArticleLike(userId: number, articleId: number) { + return prisma.like.findUnique({ + where: { userId_articleId: { userId, articleId } }, + }); + } + + async findProductLike(userId: number, productId: number) { + return prisma.like.findUnique({ + where: { userId_productId: { userId, productId } }, + }); + } + + async toggleArticleLike(userId: number, articleId: number, current: boolean) { + return prisma.like.update({ + where: { userId_articleId: { userId, articleId } }, + data: { like: !current }, + }); + } + + async toggleProductLike(userId: number, productId: number, current: boolean) { + return prisma.like.update({ + where: { userId_productId: { userId, productId } }, + data: { like: !current }, + }); + } + + async createArticleLike(userId: number, articleId: number) { + return prisma.like.create({ + data: { like: true, userId, articleId }, + }); + } + + async createProductLike(userId: number, productId: number) { + return prisma.like.create({ + data: { like: true, userId, productId }, + }); + } + + async findLikedArticles(userId: number) { + return prisma.like.findMany({ + where: { userId, articleId: { not: null }, like: true }, + include: { + article: { select: { id: true, title: true } }, + }, + }); + } + + async findLikedProducts(userId: number) { + return prisma.like.findMany({ + where: { userId, productId: { not: null }, like: true }, + include: { + product: { select: { id: true, name: true, price: true, tags: true } }, + }, + }); + } +} \ No newline at end of file diff --git a/mission 8/src/repositories/productRepository.ts b/mission 8/src/repositories/productRepository.ts new file mode 100644 index 000000000..62b287709 --- /dev/null +++ b/mission 8/src/repositories/productRepository.ts @@ -0,0 +1,49 @@ +import prisma from "../lib/prisma"; +import { Prisma } from "@prisma/client"; +import { ProductCreateDTO, ProductUpdateDTO, ProductQueryDTO } from "../dtos/product.dto"; + +export class ProductRepository { + async createProduct(data: { userId: number; name: string; description: string; price: number; tags: string }) { + return prisma.product.create({ data }); + } + + async findMany(where: Prisma.ProductWhereInput, skip: number, take: number) { + return prisma.product.findMany({ + skip, + take, + orderBy: { createdAt: "desc" }, + select: { + id: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + where, + }); + } + + async findById(id: number) { + return prisma.product.findUnique({ + where: { id }, + select: { + id: true, + userId: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + }); + } + + async updateProduct(id: number, data: Partial<{ name: string; description: string; price: number; tags: string }>) { + return prisma.product.update({ where: { id }, data }); + } + + async deleteProduct(id: number) { + return prisma.product.delete({ where: { id } }); + } +} \ No newline at end of file diff --git a/mission 8/src/repositories/userRepository.ts b/mission 8/src/repositories/userRepository.ts new file mode 100644 index 000000000..e2eb38b76 --- /dev/null +++ b/mission 8/src/repositories/userRepository.ts @@ -0,0 +1,29 @@ +import prisma from "../lib/prisma"; + +export class UserRepository { + async findByEmail(email: string) { + return prisma.user.findUnique({ where: { email } }); + } + + async findById(id: number) { + return prisma.user.findUnique({ + where: { id }, + select: { id: true, email: true, nickname: true, image: true, createdAt: true, updatedAt: true }, + }); + } + + async createUser(email: string, nickname: string, password: string) { + return prisma.user.create({ data: { email, nickname, password } }); + } + + async updateUser(id: number, data: Partial<{ nickname: string; image: string; password: string }>) { + return prisma.user.update({ where: { id }, data }); + } + + async findProductsByUserId(userId: number) { + return prisma.product.findMany({ + where: { userId }, + select: { name: true, description: true, price: true, tags: true }, + }); + } +} \ No newline at end of file diff --git a/mission 8/src/routers/articleRouter.ts b/mission 8/src/routers/articleRouter.ts new file mode 100644 index 000000000..4c4161a6b --- /dev/null +++ b/mission 8/src/routers/articleRouter.ts @@ -0,0 +1,14 @@ +import express from "express"; +import passport from "../lib/passport"; +import { ArticleController } from "../controllers/articleController"; + +const router = express.Router(); +const controller = new ArticleController(); + +router.post("/", passport.authenticate("access-token", { session: false }), controller.create); +router.get("/", passport.authenticate("access-token", { session: false }), controller.list); +router.get("/:id", passport.authenticate("access-token", { session: false }), controller.detail); +router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update); +router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete); + +export default router; \ No newline at end of file diff --git a/mission 8/src/routers/commentRouter.ts b/mission 8/src/routers/commentRouter.ts new file mode 100644 index 000000000..f7b6b4903 --- /dev/null +++ b/mission 8/src/routers/commentRouter.ts @@ -0,0 +1,15 @@ +import express from "express"; +import passport from "../lib/passport"; +import { CommentController } from "../controllers/commentController"; + +const router = express.Router(); +const controller = new CommentController(); + +router.post("/products/:id", passport.authenticate("access-token", { session: false }), controller.createProductComment); +router.post("/articles/:id", passport.authenticate("access-token", { session: false }), controller.createArticleComment); +router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.modifyComment); +router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.deleteComment); +router.get("/products/:id", passport.authenticate("access-token", { session: false }), controller.productCommentList); +router.get("/articles/:id", passport.authenticate("access-token", { session: false }), controller.articleCommentList); + +export default router; \ No newline at end of file diff --git a/mission 8/src/routers/index.ts b/mission 8/src/routers/index.ts new file mode 100644 index 000000000..c1bafd4f0 --- /dev/null +++ b/mission 8/src/routers/index.ts @@ -0,0 +1,19 @@ +import express from "express"; + +import userRouter from "./userRouter"; +import articleRouter from "./articleRouter"; +import productRouter from "./productRouter"; +import commentRouter from "./commentRouter"; +import likeRouter from "./likeRouter"; +import photoRouter from "./photoRouter"; // ✅ 공통 업로드 전용 + +const router = express.Router(); + +router.use("/users", userRouter); +router.use("/articles", articleRouter); +router.use("/products", productRouter); +router.use("/comments", commentRouter); +router.use("/likes", likeRouter); +router.use(photoRouter); // 📌 prefix는 /photos + +export default router; \ No newline at end of file diff --git a/mission 8/src/routers/likeRouter.ts b/mission 8/src/routers/likeRouter.ts new file mode 100644 index 000000000..10ec9924d --- /dev/null +++ b/mission 8/src/routers/likeRouter.ts @@ -0,0 +1,13 @@ +import express from "express"; +import passport from "../lib/passport"; +import { LikeController } from "../controllers/likeController"; + +const router = express.Router(); +const controller = new LikeController(); + +router.post("/articles/:id", passport.authenticate("access-token", { session: false }), controller.likeArticle); +router.post("/products/:id", passport.authenticate("access-token", { session: false }), controller.likeProduct); +router.get("/articles", passport.authenticate("access-token", { session: false }), controller.getLikedArticles); +router.get("/products", passport.authenticate("access-token", { session: false }), controller.getLikedProducts); + +export default router; \ No newline at end of file diff --git a/mission 8/src/routers/photoRouter.ts b/mission 8/src/routers/photoRouter.ts new file mode 100644 index 000000000..796ba57b4 --- /dev/null +++ b/mission 8/src/routers/photoRouter.ts @@ -0,0 +1,17 @@ +import express from "express"; +import multer from "multer"; +import passport from "../lib/passport"; +import { PhotoController } from "../controllers/photoController"; + +const router = express.Router(); +const upload = multer({ dest: "uploads/" }); +const controller = new PhotoController(); + +router.post( + "/", + passport.authenticate("access-token", { session: false }), + upload.single("image"), + controller.upload +); + +export default router; diff --git a/mission 8/src/routers/productRouter.ts b/mission 8/src/routers/productRouter.ts new file mode 100644 index 000000000..63f2d5d87 --- /dev/null +++ b/mission 8/src/routers/productRouter.ts @@ -0,0 +1,14 @@ +import express from "express"; +import passport from "../lib/passport"; +import { ProductController } from "../controllers/productController"; + +const router = express.Router(); +const controller = new ProductController(); + +router.post("/", passport.authenticate("access-token", { session: false }), controller.create); +router.get("/", controller.list); +router.get("/:id", passport.authenticate("access-token", { session: false }), controller.list); +router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update); +router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete); + +export default router; \ No newline at end of file diff --git a/mission 8/src/routers/userRouter.ts b/mission 8/src/routers/userRouter.ts new file mode 100644 index 000000000..0df2f4317 --- /dev/null +++ b/mission 8/src/routers/userRouter.ts @@ -0,0 +1,17 @@ +import express from "express"; +import passport from "../lib/passport"; +import { UserController } from "../controllers/userController"; + +const router = express.Router(); +const controller = new UserController(); + +router.post("/register", controller.register); +router.post("/login", passport.authenticate("local", { session: false }), controller.login); +router.get("/profile", passport.authenticate("access-token", { session: false }), controller.profile); +router.patch("/modifyInformation", passport.authenticate("access-token", { session: false }), controller.modifyInformation); +router.patch("/modifyPassword", passport.authenticate("access-token", { session: false }), controller.modifyPassword); +router.get("/products", passport.authenticate("access-token", { session: false }), controller.products); +router.post("/refresh", passport.authenticate("refresh-token", { session: false }), controller.refreshTokens); +router.post("/logout", controller.logout); + +export default router; diff --git a/mission 8/src/services/articleService.ts b/mission 8/src/services/articleService.ts new file mode 100644 index 000000000..276bad3df --- /dev/null +++ b/mission 8/src/services/articleService.ts @@ -0,0 +1,44 @@ +import { ArticleRepository } from "../repositories/articleRepository"; +import type { ArticleCreateDTO, ArticleUpdateDTO, ArticleQueryDTO } from "../dtos/article.dto"; +import type { Prisma } from "@prisma/client"; + +export class ArticleService { + private repo = new ArticleRepository(); + + async create(userId: number, data: ArticleCreateDTO) { + return this.repo.createArticle({ ...data, userId }); + } + + async list({ page, pageSize, keyword }: ArticleQueryDTO) { + const where: Prisma.ArticleWhereInput = keyword + ? { + OR: [ + { title: { contains: keyword, mode: "insensitive" } }, + { content: { contains: keyword, mode: "insensitive" } }, + ], + } + : {}; + + return this.repo.findMany(where, (page - 1) * pageSize, pageSize); + } + + async getDetail(id: number) { + return this.repo.findById(id); + } + + async update(userId: number, articleId: number, data: { title?: string; content?: string; }) { + const article = await this.repo.findById(articleId); + if (!article) throw new Error("NOT_FOUND"); + if (article.userId !== userId) throw new Error("FORBIDDEN"); + + return this.repo.updatedArticle(articleId, data); + } + + async delete(userId: number, articleId: number) { + const article = await this.repo.findById(articleId); + if (!article) throw new Error("NOT_FOUND"); + if (article.userId !== userId) throw new Error("FORBIDDEN"); + + await this.repo.deleteArticle(articleId); + } +} diff --git a/mission 8/src/services/commentService.ts b/mission 8/src/services/commentService.ts new file mode 100644 index 000000000..a1b7a218f --- /dev/null +++ b/mission 8/src/services/commentService.ts @@ -0,0 +1,35 @@ +import { CommentRepository } from "../repositories/commentRepository"; + +export class CommentService { + private repo = new CommentRepository(); + + async createProductComment(userId: number, productId: number, content: string) { + return this.repo.createProductComment(userId, productId, content); + } + + async createArticleComment(userId: number, articleId: number, content: string) { + return this.repo.createArticleComment(userId, articleId, content); + } + + async updateComment(userId: number, commentId: number, content: string) { + const comment = await this.repo.findById(commentId); + if (!comment) throw new Error("NOT_FOUND"); + if (comment.userId !== userId) throw new Error("FORBIDDEN"); + return this.repo.updateComment(commentId, content); + } + + async deleteComment(userId: number, commentId: number) { + const comment = await this.repo.findById(commentId); + if (!comment) throw new Error("NOT_FOUND"); + if (comment.userId !== userId) throw new Error("FORBIDDEN"); + await this.repo.deleteComment(commentId); + } + + async getProductComments(productId: number, lastId?: number) { + return this.repo.findProductComments(productId, lastId); + } + + async getArticleComments(articleId: number, lastId?: number) { + return this.repo.findArticleComments(articleId, lastId); + } +} diff --git a/mission 8/src/services/likeService.ts b/mission 8/src/services/likeService.ts new file mode 100644 index 000000000..4f7118e7f --- /dev/null +++ b/mission 8/src/services/likeService.ts @@ -0,0 +1,35 @@ +import { LikeRepository } from "../repositories/likeRepository"; + +export class LikeService { + private repo = new LikeRepository(); + + async likeArticle(userId: number, articleId: number) { + const article = await this.repo.findArticle(articleId); + if (!article) throw new Error("ARTICLE_NOT_FOUND"); + + const existing = await this.repo.findArticleLike(userId, articleId); + if (existing) { + return this.repo.toggleArticleLike(userId, articleId, existing.like); + } + return this.repo.createArticleLike(userId, articleId); + } + + async likeProduct(userId: number, productId: number) { + const product = await this.repo.findProduct(productId); + if (!product) throw new Error("PRODUCT_NOT_FOUND"); + + const existing = await this.repo.findProductLike(userId, productId); + if (existing) { + return this.repo.toggleProductLike(userId, productId, existing.like); + } + return this.repo.createProductLike(userId, productId); + } + + async getLikedArticles(userId: number) { + return this.repo.findLikedArticles(userId); + } + + async getLikedProducts(userId: number) { + return this.repo.findLikedProducts(userId); + } +} \ No newline at end of file diff --git a/mission 8/src/services/productService.ts b/mission 8/src/services/productService.ts new file mode 100644 index 000000000..32933402e --- /dev/null +++ b/mission 8/src/services/productService.ts @@ -0,0 +1,43 @@ +import { ProductRepository } from "../repositories/productRepository"; +import type { ProductCreateDTO, ProductUpdateDTO, ProductQueryDTO } from "../dtos/product.dto"; +import type { Prisma } from "@prisma/client"; + +export class ProductService { + private repo = new ProductRepository(); + + async create(userId: number, data: ProductCreateDTO) { + return this.repo.createProduct({ ...data, userId }); + } + + async list({ page, pageSize, keyword }: ProductQueryDTO) { + const where: Prisma.ProductWhereInput = keyword + ? { + OR: [ + { name: { contains: keyword, mode: "insensitive" } }, + { description: { contains: keyword, mode: "insensitive" } }, + ], + } + : {}; + return this.repo.findMany(where, (page - 1) * pageSize, pageSize); + } + + async getDetail(id: number) { + return this.repo.findById(id); + } + + async update(userId: number, productId: number, data: { name?: string; description?: string; price?: number; tags?: string; }) { + const product = await this.repo.findById(productId); + if (!product) throw new Error("NOT_FOUND"); + if (product.userId !== userId) throw new Error("FORBIDDEN"); + + return this.repo.updateProduct(productId, data); + } + + async delete(userId: number, productId: number) { + const product = await this.repo.findById(productId); + if (!product) throw new Error("NOT_FOUND"); + if (product.userId !== userId) throw new Error("FORBIDDEN"); + + await this.repo.deleteProduct(productId); + } +} \ No newline at end of file diff --git a/mission 8/src/services/userService.ts b/mission 8/src/services/userService.ts new file mode 100644 index 000000000..f9bd91fc2 --- /dev/null +++ b/mission 8/src/services/userService.ts @@ -0,0 +1,48 @@ +import bcrypt from "bcrypt"; +import { UserRepository } from "../repositories/userRepository"; +import { generateTokens } from "../lib/token"; +import type { UserRegisterDTO, UserUpdateDTO, UserPasswordDTO } from "../dtos/user.dto"; + +export class UserService { + private userRepo = new UserRepository(); + + async register(data: UserRegisterDTO) { + const exists = await this.userRepo.findByEmail(data.email); + if (exists) throw new Error("EMAIL_EXISTS"); + + const salt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(data.password, salt); + + await this.userRepo.createUser(data.email, data.nickname, hashedPassword); + return { message: "User registered successfully" }; + } + + async getProfile(userId: number) { + return this.userRepo.findById(userId); + } + + async updateInformation(userId: number, nickname?: string, image?: string) { + const updateData: Record = {}; + if (nickname) updateData.nickname = nickname; + if (image) updateData.image = image; + + if (Object.keys(updateData).length === 0) throw new Error("NO_DATA"); + + return this.userRepo.updateUser(userId, updateData); + } + + async updatePassword(userId: number, data: UserPasswordDTO) { + const salt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(data.password, salt); + await this.userRepo.updateUser(userId, { password: hashedPassword }); + return { message: "Password updated successfully" }; + } + + async getProducts(userId: number) { + return this.userRepo.findProductsByUserId(userId); + } + + generateUserTokens(userId: number) { + return generateTokens(userId); + } +} diff --git a/mission 8/src/types/express.d.ts b/mission 8/src/types/express.d.ts new file mode 100644 index 000000000..6f994ace7 --- /dev/null +++ b/mission 8/src/types/express.d.ts @@ -0,0 +1,11 @@ +import type { User as PrismaUser } from "@prisma/client"; + +declare global { + namespace Express { + // Passport req.user 타입을 Prisma User로 확장 + interface User extends PrismaUser {} + } +} + +// 반드시 export {} 필요 +export {}; \ No newline at end of file diff --git a/mission 8/tsconfig.json b/mission 8/tsconfig.json new file mode 100644 index 000000000..e732234c0 --- /dev/null +++ b/mission 8/tsconfig.json @@ -0,0 +1,48 @@ +{ + // Visit https://aka.ms/tsconfig to read more about this file + "compilerOptions": { + // File Layout + "rootDir": "./src", + "outDir": "./dist", + + // Environment Settings + // See also https://aka.ms/tsconfig/module + "module": "CommonJS", + "target": "ESNext", + // "types": [], + // For nodejs: + "lib": ["esnext"], + "types": ["node", "express", "passport"], + "allowJs": true, + "checkJs": true, + // and npm install -D @types/node + + // Other Outputs + "sourceMap": true, + "declaration": true, + "declarationMap": true, + + // Stricter Typechecking Options + "noUncheckedIndexedAccess": true, + "exactOptionalPropertyTypes": true, + + // Style Options + // "noImplicitReturns": true, + // "noImplicitOverride": true, + // "noUnusedLocals": true, + // "noUnusedParameters": true, + // "noFallthroughCasesInSwitch": true, + // "noPropertyAccessFromIndexSignature": true, + + // Recommended Options + "strict": true, + "jsx": "react-jsx", + "verbatimModuleSyntax": false, + "isolatedModules": true, + "noUncheckedSideEffectImports": true, + "moduleDetection": "force", + "skipLibCheck": true, + "esModuleInterop": true, + }, + "include": ["src/**/*", "src/types/**/*"] +} \ No newline at end of file From 60029dba71ab8fca963c503a50cb659884915291 Mon Sep 17 00:00:00 2001 From: Batur-s Date: Sun, 9 Nov 2025 09:49:08 +0900 Subject: [PATCH 29/38] [feat] add alert system --- mission 8/package-lock.json | 6956 +++++++++++++---- mission 8/package.json | 5 +- mission 8/src/app.ts | 20 +- mission 8/src/controllers/alertController.ts | 21 + .../src/controllers/articleController.ts | 5 +- .../src/controllers/commentController.ts | 2 - mission 8/src/controllers/photoController.ts | 2 - mission 8/src/lib/token.ts | 2 +- mission 8/src/repositories/alertRepository.ts | 27 + .../src/repositories/articleRepository.ts | 7 +- .../src/repositories/commentRepository.ts | 4 +- mission 8/src/repositories/likeRepository.ts | 20 +- mission 8/src/routers/alertRouter.ts | 14 + mission 8/src/routers/index.ts | 2 + mission 8/src/services/alertService.ts | 26 + mission 8/src/services/articleService.ts | 4 +- mission 8/src/services/commentService.ts | 52 +- mission 8/src/services/productService.ts | 33 +- mission 8/src/socket.ts | 16 + mission 8/test.http | 36 + mission 8/tsconfig.json | 65 +- 21 files changed, 5903 insertions(+), 1416 deletions(-) create mode 100644 mission 8/src/controllers/alertController.ts create mode 100644 mission 8/src/repositories/alertRepository.ts create mode 100644 mission 8/src/routers/alertRouter.ts create mode 100644 mission 8/src/services/alertService.ts create mode 100644 mission 8/src/socket.ts create mode 100644 mission 8/test.http diff --git a/mission 8/package-lock.json b/mission 8/package-lock.json index 006cf8369..88d9d3424 100644 --- a/mission 8/package-lock.json +++ b/mission 8/package-lock.json @@ -30,1614 +30,4573 @@ "@types/cookie-parser": "^1.4.9", "@types/cors": "^2.8.19", "@types/express": "^5.0.3", + "@types/jest": "^30.0.0", "@types/jsonwebtoken": "^9.0.10", "@types/multer": "^2.0.0", "@types/node": "^24.3.1", "@types/passport": "^1.0.17", "@types/passport-jwt": "^4.0.1", "@types/passport-local": "^1.0.38", + "jest": "^30.2.0", "prisma": "^6.15.0", + "ts-jest": "^29.4.5", "ts-node": "^10.9.2", "ts-node-dev": "^2.0.0", - "typescript": "^5.9.2" + "typescript": "^5.9.3" } }, - "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==", + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", - "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/compat-data": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "aix" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", - "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", - "cpu": [ - "arm" - ], + "node_modules/@babel/core": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/remapping": "^2.3.5", + "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/@esbuild/android-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", - "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", - "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", - "cpu": [ - "x64" - ], + "node_modules/@babel/generator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", - "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", - "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", - "cpu": [ - "x64" - ], + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", - "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", - "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", - "cpu": [ - "x64" - ], + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", - "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", - "cpu": [ - "arm" - ], + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", - "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", - "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", - "cpu": [ - "ia32" - ], + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", - "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", - "cpu": [ - "loong64" - ], + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", - "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", - "cpu": [ - "mips64el" - ], + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", - "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", - "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", - "cpu": [ - "riscv64" - ], + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, "engines": { - "node": ">=18" + "node": ">=6.0.0" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", - "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", - "cpu": [ - "s390x" - ], + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", - "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "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, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/netbsd-arm64": { + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "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.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "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, + "license": "MIT" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@emnapi/core": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.0.tgz", + "integrity": "sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.0.tgz", + "integrity": "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", - "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", "cpu": [ - "arm64" + "ppc64" ], "license": "MIT", "optional": true, "os": [ - "netbsd" + "aix" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/netbsd-x64": { + "node_modules/@esbuild/android-arm": { "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", - "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", "cpu": [ - "x64" + "arm" ], "license": "MIT", "optional": true, "os": [ - "netbsd" + "android" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/openbsd-arm64": { + "node_modules/@esbuild/android-arm64": { "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", - "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ - "openbsd" + "android" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/openbsd-x64": { + "node_modules/@esbuild/android-x64": { "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", - "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ - "openbsd" + "android" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/openharmony-arm64": { + "node_modules/@esbuild/darwin-arm64": { "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", - "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ - "openharmony" + "darwin" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/sunos-x64": { + "node_modules/@esbuild/darwin-x64": { "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", - "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ - "sunos" + "darwin" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/win32-arm64": { + "node_modules/@esbuild/freebsd-arm64": { "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", - "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ - "win32" + "freebsd" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/win32-ia32": { + "node_modules/@esbuild/freebsd-x64": { "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", - "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", "cpu": [ - "ia32" + "x64" ], "license": "MIT", "optional": true, "os": [ - "win32" + "freebsd" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/win32-x64": { + "node_modules/@esbuild/linux-arm": { "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", - "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", "cpu": [ "x64" ], "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "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, + "license": "ISC", + "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.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "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.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "ISC", + "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/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.2.0.tgz", + "integrity": "sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/core": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.2.0.tgz", + "integrity": "sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.2.0", + "@jest/pattern": "30.0.1", + "@jest/reporters": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-changed-files": "30.2.0", + "jest-config": "30.2.0", + "jest-haste-map": "30.2.0", + "jest-message-util": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-resolve-dependencies": "30.2.0", + "jest-runner": "30.2.0", + "jest-runtime": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "jest-watcher": "30.2.0", + "micromatch": "^4.0.8", + "pretty-format": "30.2.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/diff-sequences": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", + "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz", + "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-mock": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "30.2.0", + "jest-snapshot": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", + "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz", + "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@sinonjs/fake-timers": "^13.0.0", + "@types/node": "*", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/get-type": { + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", + "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.2.0.tgz", + "integrity": "sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/expect": "30.2.0", + "@jest/types": "30.2.0", + "jest-mock": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/pattern": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", + "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-regex-util": "30.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.2.0.tgz", + "integrity": "sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@jridgewell/trace-mapping": "^0.3.25", + "@types/node": "*", + "chalk": "^4.1.2", + "collect-v8-coverage": "^1.0.2", + "exit-x": "^0.2.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^5.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "jest-worker": "30.2.0", + "slash": "^3.0.0", + "string-length": "^4.0.2", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/snapshot-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz", + "integrity": "sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "natural-compare": "^1.4.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", + "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "callsites": "^3.1.0", + "graceful-fs": "^4.2.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/test-result": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.2.0.tgz", + "integrity": "sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.2.0", + "@jest/types": "30.2.0", + "@types/istanbul-lib-coverage": "^2.0.6", + "collect-v8-coverage": "^1.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.2.0.tgz", + "integrity": "sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.2.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz", + "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/types": "30.2.0", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.1", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-util": "30.2.0", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/types": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", + "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.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, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@prisma/client": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.13.0.tgz", + "integrity": "sha512-8m2+I3dQovkV8CkDMluiwEV1TxV9EXdT6xaCz39O6jYw7mkf5gwfmi+cL4LJsEPwz5tG7sreBwkRpEMJedGYUQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "prisma": "*", + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@prisma/config": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.15.0.tgz", + "integrity": "sha512-KMEoec9b2u6zX0EbSEx/dRpx1oNLjqJEBZYyK0S3TTIbZ7GEGoVyGyFRk4C72+A38cuPLbfQGQvgOD+gBErKlA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "c12": "3.1.0", + "deepmerge-ts": "7.1.5", + "effect": "3.16.12", + "empathic": "2.0.0" + } + }, + "node_modules/@prisma/debug": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.15.0.tgz", + "integrity": "sha512-y7cSeLuQmyt+A3hstAs6tsuAiVXSnw9T55ra77z0nbNkA8Lcq9rNcQg6PI00by/+WnE/aMRJ/W7sZWn2cgIy1g==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.15.0.tgz", + "integrity": "sha512-opITiR5ddFJ1N2iqa7mkRlohCZqVSsHhRcc29QXeldMljOf4FSellLT0J5goVb64EzRTKcIDeIsJBgmilNcKxA==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/fetch-engine": "6.15.0", + "@prisma/get-platform": "6.15.0" + } + }, + "node_modules/@prisma/engines-version": { + "version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb.tgz", + "integrity": "sha512-a/46aK5j6L3ePwilZYEgYDPrhBQ/n4gYjLxT5YncUTJJNRnTCVjPF86QdzUOLRdYjCLfhtZp9aum90W0J+trrg==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.15.0.tgz", + "integrity": "sha512-xcT5f6b+OWBq6vTUnRCc7qL+Im570CtwvgSj+0MTSGA1o9UDSKZ/WANvwtiRXdbYWECpyC3CukoG3A04VTAPHw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/get-platform": "6.15.0" + } + }, + "node_modules/@prisma/get-platform": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.15.0.tgz", + "integrity": "sha512-Jbb+Xbxyp05NSR1x2epabetHiXvpO8tdN2YNoWoA/ZsbYyxxu/CO/ROBauIFuMXs3Ti+W7N7SJtWsHGaWte9Rg==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", + "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "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.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-/oJGukuH3D2+D+3H4JWLaAsJ/ji86dhRidzZ/Od7H/i8g+aCmvkeCc6Ni/f9uxGLSQVCRZkX2/lqEFG2BvWtlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie-parser": { + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.9.tgz", + "integrity": "sha512-tGZiZ2Gtc4m3wIdLkZ8mkj1T6CEHb35+VApbL2T14Dew8HA7c+04dmKqsKRNC+8RJPm16JEK0tFSwdZqubfc4g==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz", + "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", + "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", + "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^30.0.0", + "pretty-format": "^30.0.0" + } + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/multer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz", + "integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/node": { + "version": "24.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz", + "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~7.10.0" + } + }, + "node_modules/@types/passport": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", + "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/passport-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-Y0Ykz6nWP4jpxgEUYq8NoVZeCQPo1ZndJLfapI249g1jHChvRfZRO/LS3tqu26YgAS/laI1qx98sYGz0IalRXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/jsonwebtoken": "*", + "@types/passport-strategy": "*" + } + }, + "node_modules/@types/passport-local": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.38.tgz", + "integrity": "sha512-nsrW4A963lYE7lNTv9cr5WmiUD1ibYJvWrpE13oxApFsRt77b0RdtZvKbCdNIY4v/QZ6TRQWaDDEwV1kCTmcXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-strategy": "*" + } + }, + "node_modules/@types/passport-strategy": { + "version": "0.2.38", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", + "integrity": "sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", + "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.8", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", + "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/strip-json-comments": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", + "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.34", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.34.tgz", + "integrity": "sha512-KExbHVa92aJpw9WDQvzBaGVE2/Pz+pLZQloT2hjL8IqsZnV62rlPOYvNnLmf/L2dyllfVUOVBj64M0z/46eR2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "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, + "license": "ISC", + "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==", + "license": "MIT" + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/babel-jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.2.0.tgz", + "integrity": "sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "30.2.0", + "@types/babel__core": "^7.20.5", + "babel-plugin-istanbul": "^7.0.1", + "babel-preset-jest": "30.2.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0 || ^8.0.0-0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz", + "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==", + "dev": true, + "license": "BSD-3-Clause", + "workspaces": [ + "test/babel-8" + ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.2.0.tgz", + "integrity": "sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/babel__core": "^7.20.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.2.0.tgz", + "integrity": "sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "30.2.0", + "babel-preset-current-node-syntax": "^1.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0 || ^8.0.0-beta.1" + } + }, + "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, + "license": "MIT" + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.23", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.23.tgz", + "integrity": "sha512-616V5YX4bepJFzNyOfce5Fa8fDJMfoxzOIzDCZwaGL8MKVpFrXqfNUoIpRn9YMI5pXf/VKgzjB4htFMsFKKdiQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.0", + "node-gyp-build": "^4.8.4" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.27.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz", + "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", + "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" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.8.19", + "caniuse-lite": "^1.0.30001751", + "electron-to-chromium": "^1.5.238", + "node-releases": "^2.0.26", + "update-browserslist-db": "^1.1.4" + }, + "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, + "license": "MIT", + "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, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "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==", + "license": "BSD-3-Clause" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/c12": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", + "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.3", + "confbox": "^0.2.2", + "defu": "^6.1.4", + "dotenv": "^16.6.1", + "exsolve": "^1.0.7", + "giget": "^2.0.0", + "jiti": "^2.4.2", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^1.0.0", + "pkg-types": "^2.2.0", + "rc9": "^2.1.2" + }, + "peerDependencies": { + "magicast": "^0.3.5" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } + } + }, + "node_modules/c12/node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "devOptional": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001753", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001753.tgz", + "integrity": "sha512-Bj5H35MD/ebaOV4iDLqPEtiliTN29qkGtEHCwawWn4cYm+bPJM2NsaP30vtZcnERClMzp52J4+aw2UNbK4o+zw==", + "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" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ci-info": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "consola": "^3.2.3" + } + }, + "node_modules/cjs-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.1.0.tgz", + "integrity": "sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "license": "MIT", + "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==", + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "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, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", + "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": 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, + "license": "MIT", "engines": { - "node": ">=18" + "node": ">=0.10.0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, + "node_modules/deepmerge-ts": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", + "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "license": "MIT", "engines": { - "node": ">=6.0.0" + "node": ">= 0.8" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "devOptional": true, "license": "MIT" }, - "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==", + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "engines": { + "node": ">=8" } }, - "node_modules/@prisma/client": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.13.0.tgz", - "integrity": "sha512-8m2+I3dQovkV8CkDMluiwEV1TxV9EXdT6xaCz39O6jYw7mkf5gwfmi+cL4LJsEPwz5tG7sreBwkRpEMJedGYUQ==", - "hasInstallScript": true, - "license": "Apache-2.0", + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", "engines": { - "node": ">=18.18" - }, - "peerDependencies": { - "prisma": "*", - "typescript": ">=5.1.0" - }, - "peerDependenciesMeta": { - "prisma": { - "optional": true - }, - "typescript": { - "optional": true - } + "node": ">=0.3.1" } }, - "node_modules/@prisma/config": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.15.0.tgz", - "integrity": "sha512-KMEoec9b2u6zX0EbSEx/dRpx1oNLjqJEBZYyK0S3TTIbZ7GEGoVyGyFRk4C72+A38cuPLbfQGQvgOD+gBErKlA==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "c12": "3.1.0", - "deepmerge-ts": "7.1.5", - "effect": "3.16.12", - "empathic": "2.0.0" + "node_modules/dotenv": { + "version": "17.2.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", + "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/@prisma/debug": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.15.0.tgz", - "integrity": "sha512-y7cSeLuQmyt+A3hstAs6tsuAiVXSnw9T55ra77z0nbNkA8Lcq9rNcQg6PI00by/+WnE/aMRJ/W7sZWn2cgIy1g==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@prisma/engines": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.15.0.tgz", - "integrity": "sha512-opITiR5ddFJ1N2iqa7mkRlohCZqVSsHhRcc29QXeldMljOf4FSellLT0J5goVb64EzRTKcIDeIsJBgmilNcKxA==", - "devOptional": true, - "hasInstallScript": true, - "license": "Apache-2.0", + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", "dependencies": { - "@prisma/debug": "6.15.0", - "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", - "@prisma/fetch-engine": "6.15.0", - "@prisma/get-platform": "6.15.0" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/@prisma/engines-version": { - "version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb.tgz", - "integrity": "sha512-a/46aK5j6L3ePwilZYEgYDPrhBQ/n4gYjLxT5YncUTJJNRnTCVjPF86QdzUOLRdYjCLfhtZp9aum90W0J+trrg==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@prisma/fetch-engine": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.15.0.tgz", - "integrity": "sha512-xcT5f6b+OWBq6vTUnRCc7qL+Im570CtwvgSj+0MTSGA1o9UDSKZ/WANvwtiRXdbYWECpyC3CukoG3A04VTAPHw==", - "devOptional": true, - "license": "Apache-2.0", + "node_modules/dynamic-dedupe": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", + "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", + "dev": true, + "license": "MIT", "dependencies": { - "@prisma/debug": "6.15.0", - "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", - "@prisma/get-platform": "6.15.0" + "xtend": "^4.0.0" } }, - "node_modules/@prisma/get-platform": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.15.0.tgz", - "integrity": "sha512-Jbb+Xbxyp05NSR1x2epabetHiXvpO8tdN2YNoWoA/ZsbYyxxu/CO/ROBauIFuMXs3Ti+W7N7SJtWsHGaWte9Rg==", - "devOptional": true, + "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, + "license": "MIT" + }, + "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==", "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "6.15.0" + "safe-buffer": "^5.0.1" } }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, - "node_modules/@standard-schema/spec": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", - "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "node_modules/effect": { + "version": "3.16.12", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.16.12.tgz", + "integrity": "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==", "devOptional": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "fast-check": "^3.23.1" + } }, - "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==", + "node_modules/electron-to-chromium": { + "version": "1.5.244", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.244.tgz", + "integrity": "sha512-OszpBN7xZX4vWMPJwB9illkN/znA8M36GQqQxi6MNy9axWxhOfJyZZJtSLQCpEFLHP2xK33BiWx9aIuIEXVCcw==", "dev": true, - "license": "MIT" + "license": "ISC" }, - "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==", + "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, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } }, - "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==", + "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, "license": "MIT" }, - "node_modules/@types/bcrypt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-6.0.0.tgz", - "integrity": "sha512-/oJGukuH3D2+D+3H4JWLaAsJ/ji86dhRidzZ/Od7H/i8g+aCmvkeCc6Ni/f9uxGLSQVCRZkX2/lqEFG2BvWtlQ==", - "dev": true, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "devOptional": true, "license": "MIT", - "dependencies": { - "@types/node": "*" + "engines": { + "node": ">=14" } }, - "node_modules/@types/body-parser": { - "version": "1.19.6", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", - "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", - "dev": true, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" + "engines": { + "node": ">= 0.8" } }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, + "node_modules/engine.io": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", + "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", "license": "MIT", "dependencies": { - "@types/node": "*" + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.7.2", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1" + }, + "engines": { + "node": ">=10.2.0" } }, - "node_modules/@types/cookie-parser": { - "version": "1.4.9", - "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.9.tgz", - "integrity": "sha512-tGZiZ2Gtc4m3wIdLkZ8mkj1T6CEHb35+VApbL2T14Dew8HA7c+04dmKqsKRNC+8RJPm16JEK0tFSwdZqubfc4g==", - "dev": true, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", "license": "MIT", - "peerDependencies": { - "@types/express": "*" + "engines": { + "node": ">=10.0.0" } }, - "node_modules/@types/cors": { - "version": "2.8.19", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", - "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "node_modules/engine.io/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "license": "MIT", "dependencies": { - "@types/node": "*" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/@types/express": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz", - "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==", - "dev": true, + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "license": "MIT", - "peer": true, "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^5.0.0", - "@types/serve-static": "*" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@types/express-serve-static-core": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", - "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", - "dev": true, + "node_modules/engine.io/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" + "engines": { + "node": ">= 0.6" } }, - "node_modules/@types/http-errors": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", - "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/jsonwebtoken": { - "version": "9.0.10", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", - "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", - "dev": true, + "node_modules/engine.io/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { - "@types/ms": "*", - "@types/node": "*" + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true, - "license": "MIT" + "node_modules/engine.io/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "dev": true, - "license": "MIT" + "node_modules/engine.io/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } }, - "node_modules/@types/multer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz", - "integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==", + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/express": "*" + "is-arrayish": "^0.2.1" } }, - "node_modules/@types/node": { - "version": "24.3.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz", - "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==", + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", - "peer": true, - "dependencies": { - "undici-types": "~7.10.0" + "engines": { + "node": ">= 0.4" } }, - "node_modules/@types/passport": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", - "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==", - "dev": true, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", - "dependencies": { - "@types/express": "*" + "engines": { + "node": ">= 0.4" } }, - "node_modules/@types/passport-jwt": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-4.0.1.tgz", - "integrity": "sha512-Y0Ykz6nWP4jpxgEUYq8NoVZeCQPo1ZndJLfapI249g1jHChvRfZRO/LS3tqu26YgAS/laI1qx98sYGz0IalRXQ==", - "dev": true, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", "dependencies": { - "@types/jsonwebtoken": "*", - "@types/passport-strategy": "*" + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/@types/passport-local": { - "version": "1.0.38", - "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.38.tgz", - "integrity": "sha512-nsrW4A963lYE7lNTv9cr5WmiUD1ibYJvWrpE13oxApFsRt77b0RdtZvKbCdNIY4v/QZ6TRQWaDDEwV1kCTmcXg==", - "dev": true, + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "@types/express": "*", - "@types/passport": "*", - "@types/passport-strategy": "*" + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" } }, - "node_modules/@types/passport-strategy": { - "version": "0.2.38", - "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", - "integrity": "sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==", + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", - "dependencies": { - "@types/express": "*", - "@types/passport": "*" + "engines": { + "node": ">=6" } }, - "node_modules/@types/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "license": "MIT" }, - "node_modules/@types/send": { - "version": "0.17.5", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", - "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, "license": "MIT", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "engines": { + "node": ">=8" } }, - "node_modules/@types/serve-static": { - "version": "1.15.8", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", - "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" } }, - "node_modules/@types/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", - "dev": true, - "license": "MIT" + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } }, - "node_modules/@types/strip-json-comments": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", - "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, - "license": "MIT" - }, - "node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", "license": "MIT", "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" + "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": ">= 0.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "node_modules/exit-x": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", + "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", "dev": true, "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, "engines": { - "node": ">=0.4.0" + "node": ">= 0.8.0" } }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "node_modules/expect": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", "dev": true, "license": "MIT", "dependencies": { - "acorn": "^8.11.0" + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" }, "engines": { - "node": ">=0.4.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" }, "engines": { - "node": ">= 8" + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "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/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "devOptional": true, "license": "MIT" }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "node_modules/fast-check": { + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", + "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "dependencies": { + "pure-rand": "^6.1.0" + }, + "engines": { + "node": ">=8.0.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, "license": "MIT" }, - "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==", + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } }, - "node_modules/base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, "engines": { - "node": "^4.5.0 || >= 5.9" + "node": ">=8" } }, - "node_modules/bcrypt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", - "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", - "hasInstallScript": true, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", "license": "MIT", "dependencies": { - "node-addon-api": "^8.3.0", - "node-gyp-build": "^4.8.4" + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" }, "engines": { - "node": ">= 18" + "node": ">= 0.8" } }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/body-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", - "license": "MIT", + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.0", - "http-errors": "^2.0.0", - "iconv-lite": "^0.6.3", - "on-finished": "^2.4.1", - "qs": "^6.14.0", - "raw-body": "^3.0.0", - "type-is": "^2.0.0" + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "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, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=8" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "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==", - "license": "BSD-3-Clause" - }, - "node_modules/buffer-from": { + "node_modules/function-bind": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "license": "MIT" + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "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" - }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=10.16.0" + "node": ">=6.9.0" } }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", + "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, + "license": "ISC", "engines": { - "node": ">= 0.8" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/c12": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", - "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", - "devOptional": true, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { - "chokidar": "^4.0.3", - "confbox": "^0.2.2", - "defu": "^6.1.4", - "dotenv": "^16.6.1", - "exsolve": "^1.0.7", - "giget": "^2.0.0", - "jiti": "^2.4.2", - "ohash": "^2.0.11", - "pathe": "^2.0.3", - "perfect-debounce": "^1.0.0", - "pkg-types": "^2.2.0", - "rc9": "^2.1.2" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, - "peerDependencies": { - "magicast": "^0.3.5" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "magicast": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/c12/node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "devOptional": true, - "license": "BSD-2-Clause", + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" + "node": ">=8.0.0" } }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" } }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "devOptional": true, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", "license": "MIT", "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" + "resolve-pkg-maps": "^1.0.0" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/citty": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", - "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "node_modules/giget": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", + "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", "devOptional": true, "license": "MIT", "dependencies": { - "consola": "^3.2.3" + "citty": "^0.1.6", + "consola": "^3.4.0", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.6", + "nypm": "^0.6.0", + "pathe": "^2.0.3" + }, + "bin": { + "giget": "dist/cli.mjs" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "MIT" - }, - "node_modules/concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "engines": [ - "node >= 6.0" - ], - "license": "MIT", + "license": "ISC", "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/confbox": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", - "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/consola": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", - "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", - "devOptional": true, - "license": "MIT", + "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": "^14.18.0 || >=16.10.0" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", - "license": "MIT", + "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, + "license": "ISC", "dependencies": { - "safe-buffer": "5.2.1" + "is-glob": "^4.0.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==", - "license": "MIT", - "engines": { - "node": ">= 0.6" + "node": ">= 6" } }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cookie-parser": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", - "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "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, + "license": "ISC" + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, "license": "MIT", "dependencies": { - "cookie": "0.7.2", - "cookie-signature": "1.0.6" + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" }, "engines": { - "node": ">= 0.8.0" + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" } }, - "node_modules/cookie-parser/node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "license": "MIT" + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "engines": { - "node": ">=6.6.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { - "object-assign": "^4", - "vary": "^1" + "function-bind": "^1.1.2" }, "engines": { - "node": ">= 0.10" + "node": ">= 0.4" } }, - "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==", + "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, "license": "MIT" }, - "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "license": "MIT", "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deepmerge-ts": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", - "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", - "devOptional": true, - "license": "BSD-3-Clause", "engines": { - "node": ">=16.0.0" + "node": ">= 0.8" } }, - "node_modules/defu": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", - "devOptional": true, - "license": "MIT" - }, - "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==", + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/destr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", - "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", - "devOptional": true, - "license": "MIT" - }, - "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, + "node_modules/http-status": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-status/-/http-status-2.1.0.tgz", + "integrity": "sha512-O5kPr7AW7wYd/BBiOezTwnVAnmSNFY+J7hlZD2X5IOxVBetjcHAiTXhzj0gMrnojQlwy+UT1/Y3H3vJ3UlmvLA==", "license": "BSD-3-Clause", "engines": { - "node": ">=0.3.1" + "node": ">= 0.4.0" } }, - "node_modules/dotenv": { - "version": "17.2.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", - "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", - "license": "BSD-2-Clause", + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" + "node": ">=10.17.0" } }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "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==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=0.10.0" } }, - "node_modules/dynamic-dedupe": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", - "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, "license": "MIT", "dependencies": { - "xtend": "^4.0.0" - } - }, - "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==", - "license": "Apache-2.0", - "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", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/effect": { - "version": "3.16.12", - "resolved": "https://registry.npmjs.org/effect/-/effect-3.16.12.tgz", - "integrity": "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "fast-check": "^3.23.1" - } - }, - "node_modules/empathic": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", - "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", - "devOptional": true, - "license": "MIT", + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, "engines": { - "node": ">=14" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=0.8.19" } }, - "node_modules/engine.io": { - "version": "6.6.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", - "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", - "license": "MIT", + "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==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", "dependencies": { - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.7.2", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.17.1" - }, - "engines": { - "node": ">=10.2.0" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/engine.io-parser": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", - "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "license": "MIT", "engines": { - "node": ">=10.0.0" + "node": ">= 0.10" } }, - "node_modules/engine.io/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==", + "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, + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, "license": "MIT", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "binary-extensions": "^2.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/engine.io/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "hasown": "^2.0.2" }, "engines": { - "node": ">=6.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/engine.io/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==", + "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, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/engine.io/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==", + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/engine.io/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==", + "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, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=0.12.0" } }, - "node_modules/engine.io/node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, "license": "MIT", "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "node": ">=8" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, "engines": { - "node": ">= 0.4" + "node": ">=10" } }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "license": "MIT", + "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, + "license": "BSD-3-Clause", "dependencies": { - "es-errors": "^1.3.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" } }, - "node_modules/esbuild": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", - "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", - "hasInstallScript": true, + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { - "node": ">=18" + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.9", - "@esbuild/android-arm": "0.25.9", - "@esbuild/android-arm64": "0.25.9", - "@esbuild/android-x64": "0.25.9", - "@esbuild/darwin-arm64": "0.25.9", - "@esbuild/darwin-x64": "0.25.9", - "@esbuild/freebsd-arm64": "0.25.9", - "@esbuild/freebsd-x64": "0.25.9", - "@esbuild/linux-arm": "0.25.9", - "@esbuild/linux-arm64": "0.25.9", - "@esbuild/linux-ia32": "0.25.9", - "@esbuild/linux-loong64": "0.25.9", - "@esbuild/linux-mips64el": "0.25.9", - "@esbuild/linux-ppc64": "0.25.9", - "@esbuild/linux-riscv64": "0.25.9", - "@esbuild/linux-s390x": "0.25.9", - "@esbuild/linux-x64": "0.25.9", - "@esbuild/netbsd-arm64": "0.25.9", - "@esbuild/netbsd-x64": "0.25.9", - "@esbuild/openbsd-arm64": "0.25.9", - "@esbuild/openbsd-x64": "0.25.9", - "@esbuild/openharmony-arm64": "0.25.9", - "@esbuild/sunos-x64": "0.25.9", - "@esbuild/win32-arm64": "0.25.9", - "@esbuild/win32-ia32": "0.25.9", - "@esbuild/win32-x64": "0.25.9" + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "node_modules/jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.2.0.tgz", + "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", + "dev": true, "license": "MIT", + "peer": true, + "dependencies": { + "@jest/core": "30.2.0", + "@jest/types": "30.2.0", + "import-local": "^3.2.0", + "jest-cli": "30.2.0" + }, + "bin": { + "jest": "bin/jest.js" + }, "engines": { - "node": ">= 0.6" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/express": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", - "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", - "license": "MIT", - "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.0", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" + "node_modules/jest-changed-files": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.2.0.tgz", + "integrity": "sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.1.1", + "jest-util": "30.2.0", + "p-limit": "^3.1.0" }, "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/exsolve": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", - "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/fast-check": { - "version": "3.23.2", - "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", - "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", - "devOptional": true, + "node_modules/jest-circus": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.2.0.tgz", + "integrity": "sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/expect": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "co": "^4.6.0", + "dedent": "^1.6.0", + "is-generator-fn": "^2.1.0", + "jest-each": "30.2.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-runtime": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "p-limit": "^3.1.0", + "pretty-format": "30.2.0", + "pure-rand": "^7.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-circus/node_modules/pure-rand": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", + "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", + "dev": true, "funding": [ { "type": "individual", @@ -1648,379 +4607,717 @@ "url": "https://opencollective.com/fast-check" } ], + "license": "MIT" + }, + "node_modules/jest-cli": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.2.0.tgz", + "integrity": "sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==", + "dev": true, "license": "MIT", "dependencies": { - "pure-rand": "^6.1.0" + "@jest/core": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "exit-x": "^0.2.2", + "import-local": "^3.2.0", + "jest-config": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "yargs": "^17.7.2" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": ">=8.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/jest-config": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.2.0.tgz", + "integrity": "sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==", "dev": true, "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" + "@babel/core": "^7.27.4", + "@jest/get-type": "30.1.0", + "@jest/pattern": "30.0.1", + "@jest/test-sequencer": "30.2.0", + "@jest/types": "30.2.0", + "babel-jest": "30.2.0", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "deepmerge": "^4.3.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-circus": "30.2.0", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-runner": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "micromatch": "^4.0.8", + "parse-json": "^5.2.0", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "esbuild-register": ">=3.4.0", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "esbuild-register": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/jest-config/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/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, + "license": "MIT", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/finalhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", - "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "node_modules/jest-diff": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", + "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.2.0" }, "engines": { - "node": ">= 0.8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "node_modules/jest-docblock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.2.0.tgz", + "integrity": "sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==", + "dev": true, "license": "MIT", + "dependencies": { + "detect-newline": "^3.1.0" + }, "engines": { - "node": ">= 0.6" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "node_modules/jest-each": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.2.0.tgz", + "integrity": "sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==", + "dev": true, "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "jest-util": "30.2.0", + "pretty-format": "30.2.0" + }, "engines": { - "node": ">= 0.8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "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==", + "node_modules/jest-environment-node": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.2.0.tgz", + "integrity": "sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-mock": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, + "node_modules/jest-haste-map": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz", + "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.2.0", + "jest-worker": "30.2.0", + "micromatch": "^4.0.8", + "walker": "^1.0.8" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.3" } }, - "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==", + "node_modules/jest-leak-detector": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.2.0.tgz", + "integrity": "sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==", + "dev": true, "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "@jest/get-type": "30.1.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "node_modules/jest-matcher-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", + "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "jest-diff": "30.2.0", + "pretty-format": "30.2.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", + "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.2.0", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "node_modules/jest-mock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", + "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "dev": true, "license": "MIT", "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-util": "30.2.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/get-tsconfig": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", - "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.2.0.tgz", + "integrity": "sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==", + "dev": true, "license": "MIT", "dependencies": { - "resolve-pkg-maps": "^1.0.0" + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-pnp-resolver": "^1.2.3", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "slash": "^3.0.0", + "unrs-resolver": "^1.7.11" }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/giget": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", - "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", - "devOptional": true, + "node_modules/jest-resolve-dependencies": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.2.0.tgz", + "integrity": "sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==", + "dev": true, "license": "MIT", "dependencies": { - "citty": "^0.1.6", - "consola": "^3.4.0", - "defu": "^6.1.4", - "node-fetch-native": "^1.6.6", - "nypm": "^0.6.0", - "pathe": "^2.0.3" + "jest-regex-util": "30.0.1", + "jest-snapshot": "30.2.0" }, - "bin": { - "giget": "dist/cli.mjs" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/jest-runner": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.2.0.tgz", + "integrity": "sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==", "dev": true, - "license": "ISC", + "license": "MIT", "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" + "@jest/console": "30.2.0", + "@jest/environment": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.2.0", + "jest-haste-map": "30.2.0", + "jest-leak-detector": "30.2.0", + "jest-message-util": "30.2.0", + "jest-resolve": "30.2.0", + "jest-runtime": "30.2.0", + "jest-util": "30.2.0", + "jest-watcher": "30.2.0", + "jest-worker": "30.2.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-runtime": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.2.0.tgz", + "integrity": "sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/globals": "30.2.0", + "@jest/source-map": "30.0.1", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "cjs-module-lexer": "^2.1.0", + "collect-v8-coverage": "^1.0.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": "*" + "bin": { + "glob": "dist/esm/bin.mjs" }, "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==", + "node_modules/jest-runtime/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "license": "ISC", "dependencies": { - "is-glob": "^4.0.1" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "node_modules/jest-runtime/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/jest-snapshot": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.2.0.tgz", + "integrity": "sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==", + "dev": true, "license": "MIT", "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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==", + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "@jest/snapshot-utils": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "babel-preset-current-node-syntax": "^1.2.0", + "chalk": "^4.1.2", + "expect": "30.2.0", + "graceful-fs": "^4.2.11", + "jest-diff": "30.2.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "pretty-format": "30.2.0", + "semver": "^7.7.2", + "synckit": "^0.11.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", + "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "dev": true, "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, "engines": { - "node": ">= 0.8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "node_modules/jest-util/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-status": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-status/-/http-status-2.1.0.tgz", - "integrity": "sha512-O5kPr7AW7wYd/BBiOezTwnVAnmSNFY+J7hlZD2X5IOxVBetjcHAiTXhzj0gMrnojQlwy+UT1/Y3H3vJ3UlmvLA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 0.4.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "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==", + "node_modules/jest-validate": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.2.0.tgz", + "integrity": "sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==", + "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "@jest/get-type": "30.1.0", + "@jest/types": "30.2.0", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "leven": "^3.1.0", + "pretty-format": "30.2.0" }, "engines": { - "node": ">=0.10.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "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==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "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, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/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==", + "node_modules/jest-watcher": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.2.0.tgz", + "integrity": "sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==", + "dev": true, "license": "MIT", + "dependencies": { + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "jest-util": "30.2.0", + "string-length": "^4.0.2" + }, "engines": { - "node": ">= 0.10" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "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==", + "node_modules/jest-worker": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.2.0.tgz", + "integrity": "sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==", "dev": true, "license": "MIT", "dependencies": { - "binary-extensions": "^2.0.0" + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.2.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" }, "engines": { - "node": ">=8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", "dependencies": { - "hasown": "^2.0.2" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "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, + "node_modules/jiti": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", + "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "devOptional": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "bin": { + "jiti": "lib/jiti-cli.mjs" } }, - "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==", + "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, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "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==", + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, "engines": { - "node": ">=0.12.0" + "node": ">=6" } }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "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, "license": "MIT" }, - "node_modules/jiti": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", - "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", - "devOptional": 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, "license": "MIT", "bin": { - "jiti": "lib/jiti-cli.mjs" + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" } }, "node_modules/jsonwebtoken": { @@ -2066,6 +5363,36 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/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, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -2102,12 +5429,45 @@ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", "license": "MIT" }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", "license": "MIT" }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/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, + "license": "MIT", + "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", @@ -2115,6 +5475,16 @@ "dev": true, "license": "ISC" }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -2145,6 +5515,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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, + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/mime-db": { "version": "1.54.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", @@ -2166,6 +5557,16 @@ "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -2188,6 +5589,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -2264,9 +5675,32 @@ "mime-types": "~2.1.24" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.6" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" } }, + "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, + "license": "MIT" + }, "node_modules/negotiator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", @@ -2276,6 +5710,13 @@ "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, + "license": "MIT" + }, "node_modules/node-addon-api": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz", @@ -2303,6 +5744,20 @@ "node-gyp-build-test": "build-test.js" } }, + "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, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -2313,6 +5768,19 @@ "node": ">=0.10.0" } }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/nypm": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.1.tgz", @@ -2382,6 +5850,103 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "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", @@ -2438,6 +6003,16 @@ "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -2448,6 +6023,16 @@ "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -2455,6 +6040,30 @@ "dev": true, "license": "MIT" }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/path-to-regexp": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", @@ -2483,6 +6092,13 @@ "devOptional": true, "license": "MIT" }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -2496,6 +6112,29 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/pkg-types": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", @@ -2508,6 +6147,34 @@ "pathe": "^2.0.3" } }, + "node_modules/pretty-format": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/prisma": { "version": "6.15.0", "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.15.0.tgz", @@ -2615,6 +6282,13 @@ "destr": "^2.0.3" } }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -2643,6 +6317,16 @@ "url": "https://paulmillr.com/funding/" } }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -2664,6 +6348,29 @@ "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, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -2730,9 +6437,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -2784,6 +6491,29 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "license": "ISC" }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -2856,6 +6586,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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, + "license": "ISC" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/socket.io": { "version": "4.8.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", @@ -3033,30 +6780,122 @@ "source-map": "^0.6.0" } }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "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, + "license": "BSD-3-Clause" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "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, + "license": "MIT", + "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, "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "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, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { - "node": ">=10.0.0" + "node": ">=8" } }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "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, "license": "MIT", "dependencies": { - "safe-buffer": "~5.2.0" + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, "node_modules/strip-bom": { @@ -3069,6 +6908,16 @@ "node": ">=4" } }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -3079,6 +6928,19 @@ "node": ">=0.10.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==", + "dev": true, + "license": "MIT", + "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", @@ -3092,6 +6954,37 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/synckit": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/tinyexec": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", @@ -3099,6 +6992,13 @@ "devOptional": true, "license": "MIT" }, + "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, + "license": "BSD-3-Clause" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3131,12 +7031,79 @@ "tree-kill": "cli.js" } }, + "node_modules/ts-jest": { + "version": "29.4.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.5.tgz", + "integrity": "sha512-HO3GyiWn2qvTQA4kTgjDcXiMwYQt68a1Y8+JuLRVpdIzm+UOLSHgl/XqR4c6nzJkq5rOkjc02O2I7P7l/Yof0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.7.3", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jest-util": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -3274,6 +7241,14 @@ "strip-json-comments": "^2.0.0" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, "node_modules/tsx": { "version": "4.20.5", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.5.tgz", @@ -3293,6 +7268,29 @@ "fsevents": "~2.3.3" } }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/type-is": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", @@ -3314,9 +7312,9 @@ "license": "MIT" }, "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", "peer": true, @@ -3328,6 +7326,20 @@ "node": ">=14.17" } }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/undici-types": { "version": "7.10.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", @@ -3343,6 +7355,72 @@ "node": ">= 0.8" } }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", + "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" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -3365,6 +7443,32 @@ "dev": true, "license": "MIT" }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "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/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -3374,12 +7478,109 @@ "node": ">= 0.8" } }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "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/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, + "license": "MIT", + "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==", "license": "ISC" }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/write-file-atomic/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, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/ws": { "version": "8.18.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", @@ -3410,6 +7611,52 @@ "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, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "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, + "license": "MIT", + "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, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", @@ -3420,6 +7667,19 @@ "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/zod": { "version": "4.0.14", "resolved": "https://registry.npmjs.org/zod/-/zod-4.0.14.tgz", diff --git a/mission 8/package.json b/mission 8/package.json index 1bf13be55..0ebe6a2c7 100644 --- a/mission 8/package.json +++ b/mission 8/package.json @@ -34,16 +34,19 @@ "@types/cookie-parser": "^1.4.9", "@types/cors": "^2.8.19", "@types/express": "^5.0.3", + "@types/jest": "^30.0.0", "@types/jsonwebtoken": "^9.0.10", "@types/multer": "^2.0.0", "@types/node": "^24.3.1", "@types/passport": "^1.0.17", "@types/passport-jwt": "^4.0.1", "@types/passport-local": "^1.0.38", + "jest": "^30.2.0", "prisma": "^6.15.0", + "ts-jest": "^29.4.5", "ts-node": "^10.9.2", "ts-node-dev": "^2.0.0", - "typescript": "^5.9.2" + "typescript": "^5.9.3" }, "prisma": { "seed": "node prisma/seed.js" diff --git a/mission 8/src/app.ts b/mission 8/src/app.ts index 9be0a16ce..acb330d7d 100644 --- a/mission 8/src/app.ts +++ b/mission 8/src/app.ts @@ -5,6 +5,9 @@ import { PORT } from "./lib/constants"; import passport from "./lib/passport/index"; import cors from "cors"; import { errorHandler } from "./middlewares/errorHandler"; +import http from "http"; +import { Server } from "socket.io"; +import { registerSocket } from "./socket"; const app = express(); @@ -12,19 +15,30 @@ app.use(express.urlencoded({ extended: true })); app.use(express.json()); app.use(cookieParser()); + const corsOptions = { - //CORS 설정 및 whitelist로 'http://localhost:3000'을 설정 origin: "http://localhost:3000", optionSuccessStatus: 200, }; - app.use(cors(corsOptions)); + app.use(passport.initialize()); app.use(router); app.use("/download", express.static("uploads")); +app.use(errorHandler); +const server = http.createServer(app); -app.use(errorHandler); +const io = new Server(server, { + cors: { + origin: "http://localhost:3000", + methods: ["GET", "POST"], + }, +}); + +registerSocket(io); + +export { io }; app.listen(PORT, () => { console.log(`Server is running on http://localhost:${PORT}`); diff --git a/mission 8/src/controllers/alertController.ts b/mission 8/src/controllers/alertController.ts new file mode 100644 index 000000000..4399fb677 --- /dev/null +++ b/mission 8/src/controllers/alertController.ts @@ -0,0 +1,21 @@ +import { Request, Response } from "express"; +import { AlertService } from "../services/alertService"; +import status from "http-status"; + +export class AlertController { + private service = new AlertService(); + + list = async (req: Request, res: Response) => { + if (!req.user) + return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const userId = req.user.id; + const alerts = await this.service.list(userId); + res.json(alerts); + }; + + markAsRead = async (req: Request, res: Response) => { + const alertId = Number(req.params.id); + await this.service.read(alertId); + res.status(204).send(); + }; +} diff --git a/mission 8/src/controllers/articleController.ts b/mission 8/src/controllers/articleController.ts index 250dac6e8..b68458542 100644 --- a/mission 8/src/controllers/articleController.ts +++ b/mission 8/src/controllers/articleController.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import status from "http-status"; import { ArticleService } from "../services/articleService"; -import { ArticleCreateSchema, ArticleUpdateSchema, ArticleQuerySchema, ArticleUpdateDTO } from "../dtos/article.dto"; +import { ArticleCreateSchema, ArticleUpdateSchema, ArticleQuerySchema } from "../dtos/article.dto"; const articleService = new ArticleService(); @@ -42,10 +42,9 @@ export class ArticleController { async update(req: Request, res: Response, next: NextFunction) { try { if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); - const parsed = ArticleUpdateSchema.parse(req.body) as { title?: string; content?: string; }; const articleId = Number(req.params.id); - const updated = await articleService.update(req.user.id, articleId, parsed); + const updated = await articleService.update(req.user.id, parsed, articleId); res.status(status.OK).json(updated); } catch (err: any) { diff --git a/mission 8/src/controllers/commentController.ts b/mission 8/src/controllers/commentController.ts index 652dd54f7..ec81a315f 100644 --- a/mission 8/src/controllers/commentController.ts +++ b/mission 8/src/controllers/commentController.ts @@ -5,12 +5,10 @@ import { CommentService } from "../services/commentService"; const commentService = new CommentService(); -// body 검증 const commentSchema = z.object({ content: z.string().min(5).max(100), }); -// query 검증 const commentListSchema = z.object({ id: z.coerce.number().int().positive(), lastId: z.coerce.number().int().positive().optional(), diff --git a/mission 8/src/controllers/photoController.ts b/mission 8/src/controllers/photoController.ts index 0f52730ae..405ef1886 100644 --- a/mission 8/src/controllers/photoController.ts +++ b/mission 8/src/controllers/photoController.ts @@ -11,10 +11,8 @@ export class PhotoController { } try { - // 파일 저장 위치 → 지금은 로컬, 나중에 S3 같은 외부 스토리지로 확장 가능 const imageUrl = `/download/${req.file.filename}`; - // 📌 기본 동작: 유저 프로필 업데이트 const updatedUser = await prisma.user.update({ where: { id: req.user.id }, data: { image: imageUrl }, diff --git a/mission 8/src/lib/token.ts b/mission 8/src/lib/token.ts index 79a05e281..5bdb25906 100644 --- a/mission 8/src/lib/token.ts +++ b/mission 8/src/lib/token.ts @@ -1,4 +1,4 @@ -import jwt from 'jsonwebtoken'; + import jwt from 'jsonwebtoken'; import { JWT_ACCESS_TOKEN_SECRET, JWT_REFRESH_TOKEN_SECRET, diff --git a/mission 8/src/repositories/alertRepository.ts b/mission 8/src/repositories/alertRepository.ts new file mode 100644 index 000000000..71d7bf1e6 --- /dev/null +++ b/mission 8/src/repositories/alertRepository.ts @@ -0,0 +1,27 @@ +import prisma from "../lib/prisma"; + +export class AlertRepository { + async createAlert(data: { userId: number; message: string; link?: string }) { + return prisma.alert.create({ data }); + } + + async findByUserId(userId: number) { + return prisma.alert.findMany({ + where: { userId }, + orderBy: { createdAt: "desc" }, + }); + } + + async markAsRead(id: number) { + return prisma.alert.update({ + where: { id }, + data: { isRead: true }, + }); + } + + async countUnread(userId: number) { + return prisma.alert.count({ + where: { userId, isRead: false }, + }); + } +} diff --git a/mission 8/src/repositories/articleRepository.ts b/mission 8/src/repositories/articleRepository.ts index 07318b163..815428ffb 100644 --- a/mission 8/src/repositories/articleRepository.ts +++ b/mission 8/src/repositories/articleRepository.ts @@ -24,7 +24,6 @@ export class ArticleRepository { } async updatedArticle(id: number, data: { title?: string; content?: string }) { - // undefined 필드 제거 const updateData: { title?: string; content?: string } = {}; if (data.title !== undefined) updateData.title = data.title; if (data.content !== undefined) updateData.content = data.content; @@ -32,7 +31,9 @@ export class ArticleRepository { return prisma.article.update({ where: { id }, data: updateData }); } - async deleteArticle(id: number) { - return prisma.article.delete({ where: { id } }); + async deleteArticle(id: number): Promise { + await prisma.article.delete({ where: { id } }); } } + +export default new ArticleRepository(); \ No newline at end of file diff --git a/mission 8/src/repositories/commentRepository.ts b/mission 8/src/repositories/commentRepository.ts index 028695d4a..38de775ae 100644 --- a/mission 8/src/repositories/commentRepository.ts +++ b/mission 8/src/repositories/commentRepository.ts @@ -47,4 +47,6 @@ export class CommentRepository { select: { id: true, content: true, createdAt: true }, }); } -} \ No newline at end of file +} + +export default new CommentRepository(); \ No newline at end of file diff --git a/mission 8/src/repositories/likeRepository.ts b/mission 8/src/repositories/likeRepository.ts index f2b154b8f..37eb13fbf 100644 --- a/mission 8/src/repositories/likeRepository.ts +++ b/mission 8/src/repositories/likeRepository.ts @@ -64,4 +64,22 @@ export class LikeRepository { }, }); } -} \ No newline at end of file + + async findUsersWhoLikedProduct(productId: number) { + const likes = await prisma.like.findMany({ + where: { + productId, + like: true, + }, + select: { + user: { + select: { + id: true, + nickname: true, + }, + }, + }, + }); + return likes.map((like) => like.user); + } +} diff --git a/mission 8/src/routers/alertRouter.ts b/mission 8/src/routers/alertRouter.ts new file mode 100644 index 000000000..c461c7cb3 --- /dev/null +++ b/mission 8/src/routers/alertRouter.ts @@ -0,0 +1,14 @@ +import express from "express"; +import passport from "../lib/passport"; +import { AlertController } from "../controllers/alertController"; + +const router = express.Router(); +const controller = new AlertController(); + +// 내 알림 조회 +router.get("/", passport.authenticate("access-token", { session: false }), controller.list); + +// 알림 읽음 처리 +router.patch("/:id/read", passport.authenticate("access-token", { session: false }), controller.markAsRead); + +export default router; diff --git a/mission 8/src/routers/index.ts b/mission 8/src/routers/index.ts index c1bafd4f0..82c6b975b 100644 --- a/mission 8/src/routers/index.ts +++ b/mission 8/src/routers/index.ts @@ -6,6 +6,7 @@ import productRouter from "./productRouter"; import commentRouter from "./commentRouter"; import likeRouter from "./likeRouter"; import photoRouter from "./photoRouter"; // ✅ 공통 업로드 전용 +import alertRouter from "./alertRouter"; const router = express.Router(); @@ -15,5 +16,6 @@ router.use("/products", productRouter); router.use("/comments", commentRouter); router.use("/likes", likeRouter); router.use(photoRouter); // 📌 prefix는 /photos +router.use("/alerts", alertRouter); export default router; \ No newline at end of file diff --git a/mission 8/src/services/alertService.ts b/mission 8/src/services/alertService.ts new file mode 100644 index 000000000..b9d89c23f --- /dev/null +++ b/mission 8/src/services/alertService.ts @@ -0,0 +1,26 @@ +import { AlertRepository } from "../repositories/alertRepository"; +import { io } from "../app"; + +export class AlertService { + private repo = new AlertRepository(); + + async create(userId: number, message: string, link?: string) { + const alert = await this.repo.createAlert({ userId, message, link }); + + io.to(`user:${userId}`).emit("newAlert", alert); + + return alert; + } + + async list(userId: number) { + return this.repo.findByUserId(userId); + } + + async read(alertId: number) { + return this.repo.markAsRead(alertId); + } + + async countUnread(userId: number) { + return this.repo.countUnread(userId); + } +} diff --git a/mission 8/src/services/articleService.ts b/mission 8/src/services/articleService.ts index 276bad3df..885446aa9 100644 --- a/mission 8/src/services/articleService.ts +++ b/mission 8/src/services/articleService.ts @@ -26,7 +26,7 @@ export class ArticleService { return this.repo.findById(id); } - async update(userId: number, articleId: number, data: { title?: string; content?: string; }) { + async update(userId: number, data: ArticleUpdateDTO, articleId: number) { const article = await this.repo.findById(articleId); if (!article) throw new Error("NOT_FOUND"); if (article.userId !== userId) throw new Error("FORBIDDEN"); @@ -42,3 +42,5 @@ export class ArticleService { await this.repo.deleteArticle(articleId); } } + +export default new ArticleService(); \ No newline at end of file diff --git a/mission 8/src/services/commentService.ts b/mission 8/src/services/commentService.ts index a1b7a218f..e3eb961b5 100644 --- a/mission 8/src/services/commentService.ts +++ b/mission 8/src/services/commentService.ts @@ -1,14 +1,58 @@ import { CommentRepository } from "../repositories/commentRepository"; +import { ArticleRepository } from "../repositories/articleRepository"; +import { ProductRepository } from "../repositories/productRepository"; +import { AlertService } from "../services/alertService"; export class CommentService { private repo = new CommentRepository(); + private articleRepo = new ArticleRepository(); + private productRepo = new ProductRepository(); + private alertService = new AlertService(); - async createProductComment(userId: number, productId: number, content: string) { - return this.repo.createProductComment(userId, productId, content); + async createArticleComment( + userId: number, + articleId: number, + content: string + ) { + const comment = await this.repo.createArticleComment( + userId, + articleId, + content + ); + const article = await this.articleRepo.findById(articleId); + + if (article && article.userId !== userId) { + await this.alertService.create( + article.userId, + "내 게시글에 새로운 댓글이 달렸습니다.", + `/articles/${articleId}` + ); + } + + return comment; } - async createArticleComment(userId: number, articleId: number, content: string) { - return this.repo.createArticleComment(userId, articleId, content); + async createProductComment( + userId: number, + productId: number, + content: string + ) { + const comment = await this.repo.createProductComment( + userId, + productId, + content + ); + const product = await this.productRepo.findById(productId); + + if (product && product.userId !== userId) { + await this.alertService.create( + product.userId, + "내 판매글에 새로운 댓글이 달렸습니다.", + `/products/${productId}` + ); + } + + return comment; } async updateComment(userId: number, commentId: number, content: string) { diff --git a/mission 8/src/services/productService.ts b/mission 8/src/services/productService.ts index 32933402e..0b2890163 100644 --- a/mission 8/src/services/productService.ts +++ b/mission 8/src/services/productService.ts @@ -1,9 +1,13 @@ import { ProductRepository } from "../repositories/productRepository"; -import type { ProductCreateDTO, ProductUpdateDTO, ProductQueryDTO } from "../dtos/product.dto"; +import { LikeRepository } from "../repositories/likeRepository"; +import { AlertService } from "../services/alertService"; +import type { ProductCreateDTO, ProductQueryDTO } from "../dtos/product.dto"; import type { Prisma } from "@prisma/client"; export class ProductService { private repo = new ProductRepository(); + private likeRepo = new LikeRepository(); + private alertService = new AlertService(); async create(userId: number, data: ProductCreateDTO) { return this.repo.createProduct({ ...data, userId }); @@ -25,12 +29,33 @@ export class ProductService { return this.repo.findById(id); } - async update(userId: number, productId: number, data: { name?: string; description?: string; price?: number; tags?: string; }) { + async update( + userId: number, + productId: number, + data: { name?: string; description?: string; price?: number; tags?: string } + ) { const product = await this.repo.findById(productId); if (!product) throw new Error("NOT_FOUND"); if (product.userId !== userId) throw new Error("FORBIDDEN"); - return this.repo.updateProduct(productId, data); + const oldPrice = product.price; + const updated = await this.repo.updateProduct(productId, data); + + if (data.price !== undefined && data.price !== oldPrice) { + const likedUsers = await this.likeRepo.findUsersWhoLikedProduct(productId); + + const targetUsers = likedUsers.filter((u) => u.id !== userId); + + for (const user of targetUsers) { + await this.alertService.create( + user.id, + `좋아요한 상품 "${product.name}"의 가격이 ${oldPrice}원 → ${data.price}원으로 변경되었습니다.`, + `/products/${productId}` + ); + } + } + + return updated; } async delete(userId: number, productId: number) { @@ -40,4 +65,4 @@ export class ProductService { await this.repo.deleteProduct(productId); } -} \ No newline at end of file +} diff --git a/mission 8/src/socket.ts b/mission 8/src/socket.ts new file mode 100644 index 000000000..087568b1f --- /dev/null +++ b/mission 8/src/socket.ts @@ -0,0 +1,16 @@ +import { Server } from "socket.io"; + +export function registerSocket(io: Server) { + io.on("connection", (socket) => { + console.log("New client connected:", socket.id); + + socket.on("register", (userId: number) => { + socket.join(`user:${userId}`); + console.log(`User ${userId} joined room user:${userId}`); + }); + + socket.on("disconnect", () => { + console.log("Client disconnected:", socket.id); + }); + }); +} \ No newline at end of file diff --git a/mission 8/test.http b/mission 8/test.http new file mode 100644 index 000000000..cc1f46c72 --- /dev/null +++ b/mission 8/test.http @@ -0,0 +1,36 @@ +curl -X POST \ + -H "Content-Type: application/json" \ + -d '{"email": "test@example.com", "nickname": "test", "password": "password123"}' \ + http://localhost:3000/users/register + +### + curl -X POST \ + -H "Content-Type: application/json" \ + -d '{"email": "test@example.com", "password": "password123"}' \ + "http://localhost:3000/users/login" + +### + curl -X POST \ +-H "Content-Type: application/json" \ +-b "access-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsImlhdCI6MTc2MjIzMzM2MSwiZXhwIjoxNzYyMjM2OTYxfQ.NND1H5Wao2Gq_yYZz31bLtzEw9AaEGNMgD8RE-8bGKU" \ +-d '{ "title": "테스트", "content": "테스트테스트테스트테스트"}' \ +"http://localhost:3000/articles" + +### + curl -X POST \ +-H "Content-Type: application/json" \ +-b "access-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsImlhdCI6MTc2MjIzMzM2MSwiZXhwIjoxNzYyMjM2OTYxfQ.NND1H5Wao2Gq_yYZz31bLtzEw9AaEGNMgD8RE-8bGKU" \ +-d '{ "content": "덧글 테스트"}' \ +"http://localhost:3000/comments/articles/1" + +### + curl -X GET \ +-H "Content-Type: application/json" \ +-b "access-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsImlhdCI6MTc2MjI0MzQ0MiwiZXhwIjoxNzYyMjQ3MDQyfQ.kGHITSzklAyDEVQWxMZlIlUdwrcy76-UB-t_qXLySto" \ +"http://localhost:3000/comments/articles/1" + +### + curl -X GET \ +-H "Content-Type: application/json" \ +-b "access-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsImlhdCI6MTc2MjI0MzQ0MiwiZXhwIjoxNzYyMjQ3MDQyfQ.kGHITSzklAyDEVQWxMZlIlUdwrcy76-UB-t_qXLySto" \ +"http://localhost:3000/alerts/1" \ No newline at end of file diff --git a/mission 8/tsconfig.json b/mission 8/tsconfig.json index e732234c0..f052e7e3b 100644 --- a/mission 8/tsconfig.json +++ b/mission 8/tsconfig.json @@ -1,48 +1,29 @@ { - // Visit https://aka.ms/tsconfig to read more about this file "compilerOptions": { - // File Layout - "rootDir": "./src", - "outDir": "./dist", + /* ----- 기본 옵션 ----- */ + "target": "ES2020", // 어떤 버전의 JavaScript로 컴파일할지 (ES2020은 최신 Node.js와 호환성이 좋음) + "module": "commonjs", // Node.js 환경에서 사용하는 모듈 시스템 + "rootDir": "./src", // 타입스크립트 소스코드의 루트 폴더 + "outDir": "./dist", // 컴파일된 JavaScript 파일이 저장될 폴더 - // Environment Settings - // See also https://aka.ms/tsconfig/module - "module": "CommonJS", - "target": "ESNext", - // "types": [], - // For nodejs: - "lib": ["esnext"], - "types": ["node", "express", "passport"], - "allowJs": true, - "checkJs": true, - // and npm install -D @types/node + /* ----- 엄격한 타입 검사 옵션 (강력 추천) ----- */ + "strict": true, // 모든 엄격한 타입 검사 옵션을 활성화 (가장 중요!) + "noImplicitAny": true, // 'any' 타입을 명시적으로 사용하지 않으면 에러 발생 - // Other Outputs - "sourceMap": true, - "declaration": true, - "declarationMap": true, + /* ----- 모듈 관련 옵션 ----- */ + "moduleResolution": "node", // 모듈 해석 방식을 Node.js 스타일로 설정 + "esModuleInterop": true, // CommonJS 모듈을 ES 모듈 방식으로 'import' 할 수 있게 해줌 (예: import express from 'express') + "resolveJsonModule": true, // .json 파일을 모듈처럼 import 할 수 있게 허용 - // Stricter Typechecking Options - "noUncheckedIndexedAccess": true, - "exactOptionalPropertyTypes": true, - - // Style Options - // "noImplicitReturns": true, - // "noImplicitOverride": true, - // "noUnusedLocals": true, - // "noUnusedParameters": true, - // "noFallthroughCasesInSwitch": true, - // "noPropertyAccessFromIndexSignature": true, - - // Recommended Options - "strict": true, - "jsx": "react-jsx", - "verbatimModuleSyntax": false, - "isolatedModules": true, - "noUncheckedSideEffectImports": true, - "moduleDetection": "force", - "skipLibCheck": true, - "esModuleInterop": true, + /* ----- 추가 옵션 ----- */ + "sourceMap": true, // .map 파일을 생성하여, 디버깅 시 ts 코드를 볼 수 있게 함 + "forceConsistentCasingInFileNames": true, // 파일 이름의 대소문자를 구분하도록 강제 + "skipLibCheck": true, // 의존하는 라이브러리(*.d.ts)의 타입 검사를 건너뛰어 컴파일 속도 향상 + "typeRoots": ["./node_modules/@types", "./src/types"] }, - "include": ["src/**/*", "src/types/**/*"] -} \ No newline at end of file + "include": ["src/**/*"], // 컴파일할 파일 범위 (src 폴더 아래의 모든 파일) + "exclude": ["node_modules", "dist"], // 컴파일에서 제외할 폴더 + "ts-node": { + "files": true + } +} From fdaa821f84fbd44b140d120b8afca78b14b84ec6 Mon Sep 17 00:00:00 2001 From: Batur-s Date: Sun, 9 Nov 2025 10:04:29 +0900 Subject: [PATCH 30/38] [feat] mission 9 --- mission 9/.gitignore | 5 + mission 9/jest.config.ts | 9 + mission 9/package-lock.json | 7693 +++++++++++++++++ mission 9/package.json | 55 + .../20250904083711_test/migration.sql | 94 + .../20251031084424_init/migration.sql | 14 + .../prisma/migrations/migration_lock.toml | 3 + mission 9/prisma/schema.prisma | 87 + mission 9/src/app.ts | 45 + mission 9/src/controllers/alertController.ts | 21 + .../src/controllers/articleController.ts | 70 + .../src/controllers/commentController.ts | 88 + mission 9/src/controllers/likeController.ts | 51 + mission 9/src/controllers/photoController.ts | 29 + .../src/controllers/productController.ts | 68 + mission 9/src/controllers/userController.ts | 96 + mission 9/src/dtos/article.dto.ts | 38 + mission 9/src/dtos/product.dto.ts | 28 + mission 9/src/dtos/user.dto.ts | 29 + mission 9/src/lib/constants.ts | 21 + mission 9/src/lib/cookieUtil.ts | 22 + mission 9/src/lib/passport/index.ts | 9 + mission 9/src/lib/passport/jwtStrategy.ts | 45 + mission 9/src/lib/passport/localStrategy.ts | 27 + mission 9/src/lib/prisma.ts | 5 + mission 9/src/lib/token.ts | 27 + mission 9/src/middlewares/errorHandler.ts | 22 + mission 9/src/repositories/alertRepository.ts | 27 + .../src/repositories/articleRepository.ts | 39 + .../src/repositories/commentRepository.ts | 52 + mission 9/src/repositories/likeRepository.ts | 85 + .../src/repositories/productRepository.ts | 49 + mission 9/src/repositories/userRepository.ts | 29 + mission 9/src/routers/alertRouter.ts | 14 + mission 9/src/routers/articleRouter.ts | 14 + mission 9/src/routers/commentRouter.ts | 15 + mission 9/src/routers/index.ts | 21 + mission 9/src/routers/likeRouter.ts | 13 + mission 9/src/routers/photoRouter.ts | 17 + mission 9/src/routers/productRouter.ts | 14 + mission 9/src/routers/userRouter.ts | 17 + mission 9/src/services/alertService.ts | 26 + mission 9/src/services/articleService.ts | 46 + mission 9/src/services/commentService.ts | 79 + mission 9/src/services/likeService.ts | 35 + mission 9/src/services/productService.ts | 68 + mission 9/src/services/userService.ts | 48 + mission 9/src/socket.ts | 16 + mission 9/src/types/express.d.ts | 11 + mission 9/test.http | 36 + mission 9/test/articleService.test.ts | 125 + mission 9/test/commentService.test.ts | 203 + mission 9/test/hello.test.ts | 4 + mission 9/test/productService.test.ts | 121 + mission 9/tsconfig.json | 29 + 55 files changed, 9954 insertions(+) create mode 100644 mission 9/.gitignore create mode 100644 mission 9/jest.config.ts create mode 100644 mission 9/package-lock.json create mode 100644 mission 9/package.json create mode 100644 mission 9/prisma/migrations/20250904083711_test/migration.sql create mode 100644 mission 9/prisma/migrations/20251031084424_init/migration.sql create mode 100644 mission 9/prisma/migrations/migration_lock.toml create mode 100644 mission 9/prisma/schema.prisma create mode 100644 mission 9/src/app.ts create mode 100644 mission 9/src/controllers/alertController.ts create mode 100644 mission 9/src/controllers/articleController.ts create mode 100644 mission 9/src/controllers/commentController.ts create mode 100644 mission 9/src/controllers/likeController.ts create mode 100644 mission 9/src/controllers/photoController.ts create mode 100644 mission 9/src/controllers/productController.ts create mode 100644 mission 9/src/controllers/userController.ts create mode 100644 mission 9/src/dtos/article.dto.ts create mode 100644 mission 9/src/dtos/product.dto.ts create mode 100644 mission 9/src/dtos/user.dto.ts create mode 100644 mission 9/src/lib/constants.ts create mode 100644 mission 9/src/lib/cookieUtil.ts create mode 100644 mission 9/src/lib/passport/index.ts create mode 100644 mission 9/src/lib/passport/jwtStrategy.ts create mode 100644 mission 9/src/lib/passport/localStrategy.ts create mode 100644 mission 9/src/lib/prisma.ts create mode 100644 mission 9/src/lib/token.ts create mode 100644 mission 9/src/middlewares/errorHandler.ts create mode 100644 mission 9/src/repositories/alertRepository.ts create mode 100644 mission 9/src/repositories/articleRepository.ts create mode 100644 mission 9/src/repositories/commentRepository.ts create mode 100644 mission 9/src/repositories/likeRepository.ts create mode 100644 mission 9/src/repositories/productRepository.ts create mode 100644 mission 9/src/repositories/userRepository.ts create mode 100644 mission 9/src/routers/alertRouter.ts create mode 100644 mission 9/src/routers/articleRouter.ts create mode 100644 mission 9/src/routers/commentRouter.ts create mode 100644 mission 9/src/routers/index.ts create mode 100644 mission 9/src/routers/likeRouter.ts create mode 100644 mission 9/src/routers/photoRouter.ts create mode 100644 mission 9/src/routers/productRouter.ts create mode 100644 mission 9/src/routers/userRouter.ts create mode 100644 mission 9/src/services/alertService.ts create mode 100644 mission 9/src/services/articleService.ts create mode 100644 mission 9/src/services/commentService.ts create mode 100644 mission 9/src/services/likeService.ts create mode 100644 mission 9/src/services/productService.ts create mode 100644 mission 9/src/services/userService.ts create mode 100644 mission 9/src/socket.ts create mode 100644 mission 9/src/types/express.d.ts create mode 100644 mission 9/test.http create mode 100644 mission 9/test/articleService.test.ts create mode 100644 mission 9/test/commentService.test.ts create mode 100644 mission 9/test/hello.test.ts create mode 100644 mission 9/test/productService.test.ts create mode 100644 mission 9/tsconfig.json diff --git a/mission 9/.gitignore b/mission 9/.gitignore new file mode 100644 index 000000000..9f62ec0b8 --- /dev/null +++ b/mission 9/.gitignore @@ -0,0 +1,5 @@ +node_modules +# Keep environment variables out of version control +.env + +/generated/prisma diff --git a/mission 9/jest.config.ts b/mission 9/jest.config.ts new file mode 100644 index 000000000..91c17246c --- /dev/null +++ b/mission 9/jest.config.ts @@ -0,0 +1,9 @@ +module.exports = { + testEnvironment: 'node', + verbose: true, + testMatch: ['**/*.test.ts'], + transform: { + '^.+\\.ts$': 'ts-jest', + }, + moduleFileExtensions: ['ts', 'js'], +}; \ No newline at end of file diff --git a/mission 9/package-lock.json b/mission 9/package-lock.json new file mode 100644 index 000000000..88d9d3424 --- /dev/null +++ b/mission 9/package-lock.json @@ -0,0 +1,7693 @@ +{ + "name": "mission3", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mission3", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@prisma/client": "^6.13.0", + "bcrypt": "^6.0.0", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^17.2.2", + "express": "^5.1.0", + "http-status": "^2.1.0", + "multer": "^2.0.2", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", + "passport-local": "^1.0.0", + "socket.io": "^4.8.1", + "tsx": "^4.20.5", + "ws": "^8.18.3", + "zod": "^4.0.14" + }, + "devDependencies": { + "@types/bcrypt": "^6.0.0", + "@types/cookie-parser": "^1.4.9", + "@types/cors": "^2.8.19", + "@types/express": "^5.0.3", + "@types/jest": "^30.0.0", + "@types/jsonwebtoken": "^9.0.10", + "@types/multer": "^2.0.0", + "@types/node": "^24.3.1", + "@types/passport": "^1.0.17", + "@types/passport-jwt": "^4.0.1", + "@types/passport-local": "^1.0.38", + "jest": "^30.2.0", + "prisma": "^6.15.0", + "ts-jest": "^29.4.5", + "ts-node": "^10.9.2", + "ts-node-dev": "^2.0.0", + "typescript": "^5.9.3" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/remapping": "^2.3.5", + "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, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "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, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.5" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "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.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "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, + "license": "MIT" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@emnapi/core": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.0.tgz", + "integrity": "sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.0.tgz", + "integrity": "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "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, + "license": "ISC", + "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.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "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.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "ISC", + "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/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.2.0.tgz", + "integrity": "sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/core": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.2.0.tgz", + "integrity": "sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.2.0", + "@jest/pattern": "30.0.1", + "@jest/reporters": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-changed-files": "30.2.0", + "jest-config": "30.2.0", + "jest-haste-map": "30.2.0", + "jest-message-util": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-resolve-dependencies": "30.2.0", + "jest-runner": "30.2.0", + "jest-runtime": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "jest-watcher": "30.2.0", + "micromatch": "^4.0.8", + "pretty-format": "30.2.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/diff-sequences": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", + "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz", + "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-mock": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "30.2.0", + "jest-snapshot": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", + "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz", + "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@sinonjs/fake-timers": "^13.0.0", + "@types/node": "*", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/get-type": { + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", + "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.2.0.tgz", + "integrity": "sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/expect": "30.2.0", + "@jest/types": "30.2.0", + "jest-mock": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/pattern": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", + "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-regex-util": "30.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.2.0.tgz", + "integrity": "sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@jridgewell/trace-mapping": "^0.3.25", + "@types/node": "*", + "chalk": "^4.1.2", + "collect-v8-coverage": "^1.0.2", + "exit-x": "^0.2.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^5.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "jest-worker": "30.2.0", + "slash": "^3.0.0", + "string-length": "^4.0.2", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/snapshot-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz", + "integrity": "sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "natural-compare": "^1.4.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", + "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "callsites": "^3.1.0", + "graceful-fs": "^4.2.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/test-result": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.2.0.tgz", + "integrity": "sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.2.0", + "@jest/types": "30.2.0", + "@types/istanbul-lib-coverage": "^2.0.6", + "collect-v8-coverage": "^1.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.2.0.tgz", + "integrity": "sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.2.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz", + "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/types": "30.2.0", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.1", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-util": "30.2.0", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/types": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", + "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.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, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@prisma/client": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.13.0.tgz", + "integrity": "sha512-8m2+I3dQovkV8CkDMluiwEV1TxV9EXdT6xaCz39O6jYw7mkf5gwfmi+cL4LJsEPwz5tG7sreBwkRpEMJedGYUQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "prisma": "*", + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@prisma/config": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.15.0.tgz", + "integrity": "sha512-KMEoec9b2u6zX0EbSEx/dRpx1oNLjqJEBZYyK0S3TTIbZ7GEGoVyGyFRk4C72+A38cuPLbfQGQvgOD+gBErKlA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "c12": "3.1.0", + "deepmerge-ts": "7.1.5", + "effect": "3.16.12", + "empathic": "2.0.0" + } + }, + "node_modules/@prisma/debug": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.15.0.tgz", + "integrity": "sha512-y7cSeLuQmyt+A3hstAs6tsuAiVXSnw9T55ra77z0nbNkA8Lcq9rNcQg6PI00by/+WnE/aMRJ/W7sZWn2cgIy1g==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.15.0.tgz", + "integrity": "sha512-opITiR5ddFJ1N2iqa7mkRlohCZqVSsHhRcc29QXeldMljOf4FSellLT0J5goVb64EzRTKcIDeIsJBgmilNcKxA==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/fetch-engine": "6.15.0", + "@prisma/get-platform": "6.15.0" + } + }, + "node_modules/@prisma/engines-version": { + "version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb.tgz", + "integrity": "sha512-a/46aK5j6L3ePwilZYEgYDPrhBQ/n4gYjLxT5YncUTJJNRnTCVjPF86QdzUOLRdYjCLfhtZp9aum90W0J+trrg==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.15.0.tgz", + "integrity": "sha512-xcT5f6b+OWBq6vTUnRCc7qL+Im570CtwvgSj+0MTSGA1o9UDSKZ/WANvwtiRXdbYWECpyC3CukoG3A04VTAPHw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/get-platform": "6.15.0" + } + }, + "node_modules/@prisma/get-platform": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.15.0.tgz", + "integrity": "sha512-Jbb+Xbxyp05NSR1x2epabetHiXvpO8tdN2YNoWoA/ZsbYyxxu/CO/ROBauIFuMXs3Ti+W7N7SJtWsHGaWte9Rg==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", + "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "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.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-/oJGukuH3D2+D+3H4JWLaAsJ/ji86dhRidzZ/Od7H/i8g+aCmvkeCc6Ni/f9uxGLSQVCRZkX2/lqEFG2BvWtlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie-parser": { + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.9.tgz", + "integrity": "sha512-tGZiZ2Gtc4m3wIdLkZ8mkj1T6CEHb35+VApbL2T14Dew8HA7c+04dmKqsKRNC+8RJPm16JEK0tFSwdZqubfc4g==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz", + "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", + "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", + "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^30.0.0", + "pretty-format": "^30.0.0" + } + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/multer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz", + "integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/node": { + "version": "24.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz", + "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~7.10.0" + } + }, + "node_modules/@types/passport": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", + "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/passport-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-Y0Ykz6nWP4jpxgEUYq8NoVZeCQPo1ZndJLfapI249g1jHChvRfZRO/LS3tqu26YgAS/laI1qx98sYGz0IalRXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/jsonwebtoken": "*", + "@types/passport-strategy": "*" + } + }, + "node_modules/@types/passport-local": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.38.tgz", + "integrity": "sha512-nsrW4A963lYE7lNTv9cr5WmiUD1ibYJvWrpE13oxApFsRt77b0RdtZvKbCdNIY4v/QZ6TRQWaDDEwV1kCTmcXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-strategy": "*" + } + }, + "node_modules/@types/passport-strategy": { + "version": "0.2.38", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", + "integrity": "sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", + "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.8", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", + "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/strip-json-comments": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", + "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.34", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.34.tgz", + "integrity": "sha512-KExbHVa92aJpw9WDQvzBaGVE2/Pz+pLZQloT2hjL8IqsZnV62rlPOYvNnLmf/L2dyllfVUOVBj64M0z/46eR2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "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, + "license": "ISC", + "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==", + "license": "MIT" + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/babel-jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.2.0.tgz", + "integrity": "sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "30.2.0", + "@types/babel__core": "^7.20.5", + "babel-plugin-istanbul": "^7.0.1", + "babel-preset-jest": "30.2.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0 || ^8.0.0-0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz", + "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==", + "dev": true, + "license": "BSD-3-Clause", + "workspaces": [ + "test/babel-8" + ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.2.0.tgz", + "integrity": "sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/babel__core": "^7.20.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.2.0.tgz", + "integrity": "sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "30.2.0", + "babel-preset-current-node-syntax": "^1.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0 || ^8.0.0-beta.1" + } + }, + "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, + "license": "MIT" + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.23", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.23.tgz", + "integrity": "sha512-616V5YX4bepJFzNyOfce5Fa8fDJMfoxzOIzDCZwaGL8MKVpFrXqfNUoIpRn9YMI5pXf/VKgzjB4htFMsFKKdiQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.0", + "node-gyp-build": "^4.8.4" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.27.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz", + "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", + "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" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.8.19", + "caniuse-lite": "^1.0.30001751", + "electron-to-chromium": "^1.5.238", + "node-releases": "^2.0.26", + "update-browserslist-db": "^1.1.4" + }, + "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, + "license": "MIT", + "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, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "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==", + "license": "BSD-3-Clause" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/c12": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", + "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.3", + "confbox": "^0.2.2", + "defu": "^6.1.4", + "dotenv": "^16.6.1", + "exsolve": "^1.0.7", + "giget": "^2.0.0", + "jiti": "^2.4.2", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^1.0.0", + "pkg-types": "^2.2.0", + "rc9": "^2.1.2" + }, + "peerDependencies": { + "magicast": "^0.3.5" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } + } + }, + "node_modules/c12/node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "devOptional": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001753", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001753.tgz", + "integrity": "sha512-Bj5H35MD/ebaOV4iDLqPEtiliTN29qkGtEHCwawWn4cYm+bPJM2NsaP30vtZcnERClMzp52J4+aw2UNbK4o+zw==", + "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" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ci-info": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "consola": "^3.2.3" + } + }, + "node_modules/cjs-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.1.0.tgz", + "integrity": "sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "license": "MIT", + "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==", + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "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, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", + "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": 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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deepmerge-ts": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", + "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dotenv": { + "version": "17.2.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", + "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/dynamic-dedupe": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", + "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + } + }, + "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, + "license": "MIT" + }, + "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==", + "license": "Apache-2.0", + "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", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/effect": { + "version": "3.16.12", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.16.12.tgz", + "integrity": "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "fast-check": "^3.23.1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.244", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.244.tgz", + "integrity": "sha512-OszpBN7xZX4vWMPJwB9illkN/znA8M36GQqQxi6MNy9axWxhOfJyZZJtSLQCpEFLHP2xK33BiWx9aIuIEXVCcw==", + "dev": true, + "license": "ISC" + }, + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/engine.io": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", + "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", + "license": "MIT", + "dependencies": { + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.7.2", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "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/exit-x": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", + "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/fast-check": { + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", + "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "dependencies": { + "pure-rand": "^6.1.0" + }, + "engines": { + "node": ">=8.0.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, + "license": "MIT" + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "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==", + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/giget": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", + "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.0", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.6", + "nypm": "^0.6.0", + "pathe": "^2.0.3" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "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/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, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "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, + "license": "ISC" + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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, + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-status": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-status/-/http-status-2.1.0.tgz", + "integrity": "sha512-O5kPr7AW7wYd/BBiOezTwnVAnmSNFY+J7hlZD2X5IOxVBetjcHAiTXhzj0gMrnojQlwy+UT1/Y3H3vJ3UlmvLA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "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==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "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, + "license": "BSD-3-Clause", + "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": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.2.0.tgz", + "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/core": "30.2.0", + "@jest/types": "30.2.0", + "import-local": "^3.2.0", + "jest-cli": "30.2.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.2.0.tgz", + "integrity": "sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.1.1", + "jest-util": "30.2.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-circus": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.2.0.tgz", + "integrity": "sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/expect": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "co": "^4.6.0", + "dedent": "^1.6.0", + "is-generator-fn": "^2.1.0", + "jest-each": "30.2.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-runtime": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "p-limit": "^3.1.0", + "pretty-format": "30.2.0", + "pure-rand": "^7.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-circus/node_modules/pure-rand": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", + "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/jest-cli": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.2.0.tgz", + "integrity": "sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "exit-x": "^0.2.2", + "import-local": "^3.2.0", + "jest-config": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "yargs": "^17.7.2" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.2.0.tgz", + "integrity": "sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/get-type": "30.1.0", + "@jest/pattern": "30.0.1", + "@jest/test-sequencer": "30.2.0", + "@jest/types": "30.2.0", + "babel-jest": "30.2.0", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "deepmerge": "^4.3.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-circus": "30.2.0", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-runner": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "micromatch": "^4.0.8", + "parse-json": "^5.2.0", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "esbuild-register": ">=3.4.0", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "esbuild-register": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/jest-config/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/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, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-diff": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", + "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.2.0.tgz", + "integrity": "sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-each": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.2.0.tgz", + "integrity": "sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "jest-util": "30.2.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.2.0.tgz", + "integrity": "sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-mock": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz", + "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.2.0", + "jest-worker": "30.2.0", + "micromatch": "^4.0.8", + "walker": "^1.0.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.3" + } + }, + "node_modules/jest-leak-detector": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.2.0.tgz", + "integrity": "sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", + "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "jest-diff": "30.2.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", + "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.2.0", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-mock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", + "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-util": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.2.0.tgz", + "integrity": "sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-pnp-resolver": "^1.2.3", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "slash": "^3.0.0", + "unrs-resolver": "^1.7.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.2.0.tgz", + "integrity": "sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "30.0.1", + "jest-snapshot": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runner": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.2.0.tgz", + "integrity": "sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.2.0", + "@jest/environment": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.2.0", + "jest-haste-map": "30.2.0", + "jest-leak-detector": "30.2.0", + "jest-message-util": "30.2.0", + "jest-resolve": "30.2.0", + "jest-runtime": "30.2.0", + "jest-util": "30.2.0", + "jest-watcher": "30.2.0", + "jest-worker": "30.2.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-runtime": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.2.0.tgz", + "integrity": "sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/globals": "30.2.0", + "@jest/source-map": "30.0.1", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "cjs-module-lexer": "^2.1.0", + "collect-v8-coverage": "^1.0.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.2.0.tgz", + "integrity": "sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "@jest/snapshot-utils": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "babel-preset-current-node-syntax": "^1.2.0", + "chalk": "^4.1.2", + "expect": "30.2.0", + "graceful-fs": "^4.2.11", + "jest-diff": "30.2.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "pretty-format": "30.2.0", + "semver": "^7.7.2", + "synckit": "^0.11.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", + "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-util/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-validate": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.2.0.tgz", + "integrity": "sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "@jest/types": "30.2.0", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "leven": "^3.1.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.2.0.tgz", + "integrity": "sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "jest-util": "30.2.0", + "string-length": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-worker": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.2.0.tgz", + "integrity": "sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.2.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", + "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "devOptional": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "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, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "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, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=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==", + "license": "MIT", + "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.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/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, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/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, + "license": "MIT", + "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, + "license": "ISC" + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "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==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/multer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", + "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", + "object-assign": "^4.1.1", + "type-is": "^1.6.18", + "xtend": "^4.0.2" + }, + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/multer/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "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, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz", + "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "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, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nypm": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.1.tgz", + "integrity": "sha512-hlacBiRiv1k9hZFiphPUkfSQ/ZfQzZDzC+8z0wL3lvDAOUu/2NnChkKuMoMjNur/9OpKuz2QsIeiPVN0xM5Q0w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.2", + "pathe": "^2.0.3", + "pkg-types": "^2.2.0", + "tinyexec": "^1.0.1" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "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==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "license": "MIT", + "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-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", + "license": "MIT", + "dependencies": { + "jsonwebtoken": "^9.0.0", + "passport-strategy": "^1.0.0" + } + }, + "node_modules/passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, + "node_modules/pretty-format": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prisma": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.15.0.tgz", + "integrity": "sha512-E6RCgOt+kUVtjtZgLQDBJ6md2tDItLJNExwI0XJeBc1FKL+Vwb+ovxXxuok9r8oBgsOXBA33fGDuE/0qDdCWqQ==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@prisma/config": "6.15.0", + "@prisma/engines": "6.15.0" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc9": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", + "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "defu": "^6.1.4", + "destr": "^2.0.3" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "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, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "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" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "ISC" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/socket.io": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.6.0", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "license": "MIT", + "dependencies": { + "debug": "~4.3.4", + "ws": "~8.17.1" + } + }, + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-adapter/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/socket.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/socket.io/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/socket.io/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "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, + "license": "BSD-3-Clause" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.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==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/synckit": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tinyexec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", + "devOptional": true, + "license": "MIT" + }, + "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, + "license": "BSD-3-Clause" + }, + "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, + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-jest": { + "version": "29.4.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.5.tgz", + "integrity": "sha512-HO3GyiWn2qvTQA4kTgjDcXiMwYQt68a1Y8+JuLRVpdIzm+UOLSHgl/XqR4c6nzJkq5rOkjc02O2I7P7l/Yof0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.7.3", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jest-util": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "peer": 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/ts-node-dev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz", + "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.1", + "dynamic-dedupe": "^0.3.0", + "minimist": "^1.2.6", + "mkdirp": "^1.0.4", + "resolve": "^1.0.0", + "rimraf": "^2.6.1", + "source-map-support": "^0.5.12", + "tree-kill": "^1.2.2", + "ts-node": "^10.4.0", + "tsconfig": "^7.0.0" + }, + "bin": { + "ts-node-dev": "lib/bin.js", + "tsnd": "lib/bin.js" + }, + "engines": { + "node": ">=0.8.0" + }, + "peerDependencies": { + "node-notifier": "*", + "typescript": "*" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/ts-node-dev/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "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" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/ts-node-dev/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-node-dev/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/tsconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", + "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/strip-bom": "^3.0.0", + "@types/strip-json-comments": "0.0.30", + "strip-bom": "^3.0.0", + "strip-json-comments": "^2.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/tsx": { + "version": "4.20.5", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.5.tgz", + "integrity": "sha512-+wKjMNU9w/EaQayHXb7WA7ZaHY6hN8WgfvHNQ3t1PnU91/7O8TcTnIhCDYTZwnt8JsO9IBqZ30Ln1r7pPF52Aw==", + "license": "MIT", + "dependencies": { + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "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==", + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/undici-types": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", + "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" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.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==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/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, + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "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/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "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/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, + "license": "MIT", + "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==", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/write-file-atomic/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, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": 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==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "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, + "license": "MIT", + "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, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.0.14.tgz", + "integrity": "sha512-nGFJTnJN6cM2v9kXL+SOBq3AtjQby3Mv5ySGFof5UGRHrRioSJ5iG680cYNjE/yWk671nROcpPj4hAS8nyLhSw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/mission 9/package.json b/mission 9/package.json new file mode 100644 index 000000000..19bbf159c --- /dev/null +++ b/mission 9/package.json @@ -0,0 +1,55 @@ +{ + "name": "mission3", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "dev": "ts-node --files src/app.ts", + "start": "node dist/app.js", + "lint": "eslint . --ext .ts", + "prisma:generate": "prisma generate", + "prisma:migrate": "prisma migrate dev", + "test": "jest" + }, + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "@prisma/client": "^6.13.0", + "bcrypt": "^6.0.0", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^17.2.2", + "express": "^5.1.0", + "http-status": "^2.1.0", + "multer": "^2.0.2", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", + "passport-local": "^1.0.0", + "socket.io": "^4.8.1", + "tsx": "^4.20.5", + "ws": "^8.18.3", + "zod": "^4.0.14" + }, + "devDependencies": { + "@types/bcrypt": "^6.0.0", + "@types/cookie-parser": "^1.4.9", + "@types/cors": "^2.8.19", + "@types/express": "^5.0.3", + "@types/jest": "^30.0.0", + "@types/jsonwebtoken": "^9.0.10", + "@types/multer": "^2.0.0", + "@types/node": "^24.3.1", + "@types/passport": "^1.0.17", + "@types/passport-jwt": "^4.0.1", + "@types/passport-local": "^1.0.38", + "jest": "^30.2.0", + "prisma": "^6.15.0", + "ts-jest": "^29.4.5", + "ts-node": "^10.9.2", + "ts-node-dev": "^2.0.0", + "typescript": "^5.9.3" + }, + "prisma": { + "seed": "node prisma/seed.js" + } +} diff --git a/mission 9/prisma/migrations/20250904083711_test/migration.sql b/mission 9/prisma/migrations/20250904083711_test/migration.sql new file mode 100644 index 000000000..ad7fbdc5d --- /dev/null +++ b/mission 9/prisma/migrations/20250904083711_test/migration.sql @@ -0,0 +1,94 @@ +-- CreateTable +CREATE TABLE "public"."User" ( + "id" SERIAL NOT NULL, + "email" TEXT NOT NULL, + "nickname" TEXT NOT NULL, + "image" TEXT, + "password" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Product" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT NOT NULL, + "price" INTEGER NOT NULL, + "tags" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Product_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Article" ( + "id" SERIAL NOT NULL, + "title" TEXT NOT NULL, + "content" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Article_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Comment" ( + "id" SERIAL NOT NULL, + "content" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "productId" INTEGER, + "articleId" INTEGER, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Comment_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Like" ( + "id" SERIAL NOT NULL, + "like" BOOLEAN NOT NULL DEFAULT true, + "userId" INTEGER NOT NULL, + "productId" INTEGER, + "articleId" INTEGER, + + CONSTRAINT "Like_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "public"."User"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "Like_userId_productId_key" ON "public"."Like"("userId", "productId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Like_userId_articleId_key" ON "public"."Like"("userId", "articleId"); + +-- AddForeignKey +ALTER TABLE "public"."Product" ADD CONSTRAINT "Product_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Article" ADD CONSTRAINT "Article_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_productId_fkey" FOREIGN KEY ("productId") REFERENCES "public"."Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "public"."Article"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_productId_fkey" FOREIGN KEY ("productId") REFERENCES "public"."Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "public"."Article"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/mission 9/prisma/migrations/20251031084424_init/migration.sql b/mission 9/prisma/migrations/20251031084424_init/migration.sql new file mode 100644 index 000000000..2827ddec8 --- /dev/null +++ b/mission 9/prisma/migrations/20251031084424_init/migration.sql @@ -0,0 +1,14 @@ +-- CreateTable +CREATE TABLE "public"."Alert" ( + "id" SERIAL NOT NULL, + "userId" INTEGER NOT NULL, + "message" TEXT NOT NULL, + "link" TEXT, + "isRead" BOOLEAN NOT NULL DEFAULT false, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Alert_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "public"."Alert" ADD CONSTRAINT "Alert_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/mission 9/prisma/migrations/migration_lock.toml b/mission 9/prisma/migrations/migration_lock.toml new file mode 100644 index 000000000..044d57cdb --- /dev/null +++ b/mission 9/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (e.g., Git) +provider = "postgresql" diff --git a/mission 9/prisma/schema.prisma b/mission 9/prisma/schema.prisma new file mode 100644 index 000000000..a43c08252 --- /dev/null +++ b/mission 9/prisma/schema.prisma @@ -0,0 +1,87 @@ +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" +} + +model User { + id Int @id @default(autoincrement()) + email String @unique + nickname String + image String? + password String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + article Article[] + product Product[] + comment Comment[] + like Like[] + alert Alert[] +} + +model Product { + id Int @id @default(autoincrement()) + name String + description String + price Int + tags String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + comment Comment[] + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + like Like[] +} + +model Article { + id Int @id @default(autoincrement()) + title String + content String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + comment Comment[] + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + like Like[] +} + +model Comment { + id Int @id @default(autoincrement()) + content String + createdAt DateTime @default(now()) + productId Int? + product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) + articleId Int? + article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) +} + +model Like { + id Int @id @default(autoincrement()) + like Boolean @default(true) + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + productId Int? + product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) + articleId Int? + article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) + + // 유저-상품, 유저-게시글 각각 중복 방지, 좋아요 중첩 방지 + @@unique([userId, productId]) + @@unique([userId, articleId]) +} + +model Alert { + id Int @id @default(autoincrement()) + userId Int + message String + link String? + isRead Boolean @default(false) + createdAt DateTime @default(now()) + + user User @relation(fields: [userId], references: [id]) +} \ No newline at end of file diff --git a/mission 9/src/app.ts b/mission 9/src/app.ts new file mode 100644 index 000000000..acb330d7d --- /dev/null +++ b/mission 9/src/app.ts @@ -0,0 +1,45 @@ +import express from "express"; +import cookieParser from "cookie-parser"; +import router from "./routers/index"; +import { PORT } from "./lib/constants"; +import passport from "./lib/passport/index"; +import cors from "cors"; +import { errorHandler } from "./middlewares/errorHandler"; +import http from "http"; +import { Server } from "socket.io"; +import { registerSocket } from "./socket"; + +const app = express(); + +app.use(express.urlencoded({ extended: true })); + +app.use(express.json()); +app.use(cookieParser()); + +const corsOptions = { + origin: "http://localhost:3000", + optionSuccessStatus: 200, +}; +app.use(cors(corsOptions)); + +app.use(passport.initialize()); +app.use(router); +app.use("/download", express.static("uploads")); +app.use(errorHandler); + +const server = http.createServer(app); + +const io = new Server(server, { + cors: { + origin: "http://localhost:3000", + methods: ["GET", "POST"], + }, +}); + +registerSocket(io); + +export { io }; + +app.listen(PORT, () => { + console.log(`Server is running on http://localhost:${PORT}`); +}); diff --git a/mission 9/src/controllers/alertController.ts b/mission 9/src/controllers/alertController.ts new file mode 100644 index 000000000..4399fb677 --- /dev/null +++ b/mission 9/src/controllers/alertController.ts @@ -0,0 +1,21 @@ +import { Request, Response } from "express"; +import { AlertService } from "../services/alertService"; +import status from "http-status"; + +export class AlertController { + private service = new AlertService(); + + list = async (req: Request, res: Response) => { + if (!req.user) + return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const userId = req.user.id; + const alerts = await this.service.list(userId); + res.json(alerts); + }; + + markAsRead = async (req: Request, res: Response) => { + const alertId = Number(req.params.id); + await this.service.read(alertId); + res.status(204).send(); + }; +} diff --git a/mission 9/src/controllers/articleController.ts b/mission 9/src/controllers/articleController.ts new file mode 100644 index 000000000..b68458542 --- /dev/null +++ b/mission 9/src/controllers/articleController.ts @@ -0,0 +1,70 @@ +import { Request, Response, NextFunction } from "express"; +import status from "http-status"; +import { ArticleService } from "../services/articleService"; +import { ArticleCreateSchema, ArticleUpdateSchema, ArticleQuerySchema } from "../dtos/article.dto"; + +const articleService = new ArticleService(); + +export class ArticleController { + async create(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const parsed = ArticleCreateSchema.parse(req.body); + const article = await articleService.create(req.user.id, parsed); + res.status(status.CREATED).json(article); + } catch (err) { + next(err); + } + } + + async list(req: Request, res: Response, next: NextFunction) { + try { + const parsed = ArticleQuerySchema.parse(req.query); + const articles = await articleService.list(parsed); + res.status(status.OK).json(articles); + } catch (err) { + next(err); + } + } + + async detail(req: Request, res: Response, next: NextFunction) { + try { + const articleId = Number(req.params.id); + const article = await articleService.getDetail(articleId); + if (!article) return res.status(status.NOT_FOUND).json({ message: "Article not found" }); + res.status(status.OK).json(article); + } catch (err) { + next(err); + } + } + + async update(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = ArticleUpdateSchema.parse(req.body) as { title?: string; content?: string; }; + const articleId = Number(req.params.id); + const updated = await articleService.update(req.user.id, parsed, articleId); + + res.status(status.OK).json(updated); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + + async delete(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const articleId = Number(req.params.id); + await articleService.delete(req.user.id, articleId); + res.status(status.NO_CONTENT).end(); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } +} diff --git a/mission 9/src/controllers/commentController.ts b/mission 9/src/controllers/commentController.ts new file mode 100644 index 000000000..ec81a315f --- /dev/null +++ b/mission 9/src/controllers/commentController.ts @@ -0,0 +1,88 @@ +import { Request, Response, NextFunction } from "express"; +import { z } from "zod"; +import status from "http-status"; +import { CommentService } from "../services/commentService"; + +const commentService = new CommentService(); + +const commentSchema = z.object({ + content: z.string().min(5).max(100), +}); + +const commentListSchema = z.object({ + id: z.coerce.number().int().positive(), + lastId: z.coerce.number().int().positive().optional(), +}); + +export class CommentController { + async createProductComment(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const productId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const comment = await commentService.createProductComment(req.user.id, productId, parsed.content); + res.status(status.CREATED).json(comment); + } catch (err) { + next(err); + } + } + + async createArticleComment(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const articleId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const comment = await commentService.createArticleComment(req.user.id, articleId, parsed.content); + res.status(status.CREATED).json(comment); + } catch (err) { + next(err); + } + } + + async modifyComment(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const commentId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const updated = await commentService.updateComment(req.user.id, commentId, parsed.content); + res.status(status.OK).json(updated); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Comment not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + + async deleteComment(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const commentId = Number(req.params.id); + await commentService.deleteComment(req.user.id, commentId); + res.status(status.NO_CONTENT).end(); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Comment not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + + async productCommentList(req: Request, res: Response, next: NextFunction) { + try { + const parsed = commentListSchema.parse({ id: req.params.id, lastId: req.query.lastId }); + const comments = await commentService.getProductComments(parsed.id, parsed.lastId); + res.status(status.OK).json(comments); + } catch (err) { + next(err); + } + } + + async articleCommentList(req: Request, res: Response, next: NextFunction) { + try { + const parsed = commentListSchema.parse({ id: req.params.id, lastId: req.query.lastId }); + const comments = await commentService.getArticleComments(parsed.id, parsed.lastId); + res.status(status.OK).json(comments); + } catch (err) { + next(err); + } + } +} \ No newline at end of file diff --git a/mission 9/src/controllers/likeController.ts b/mission 9/src/controllers/likeController.ts new file mode 100644 index 000000000..5e4c1edba --- /dev/null +++ b/mission 9/src/controllers/likeController.ts @@ -0,0 +1,51 @@ +import { Request, Response, NextFunction } from "express"; +import status from "http-status"; +import { LikeService } from "../services/likeService"; + +const likeService = new LikeService(); + +export class LikeController { + async likeArticle(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const result = await likeService.likeArticle(req.user.id, Number(req.params.id)); + res.status(status.OK).json({ message: "Like toggled", isLiked: result.like }); + } catch (err: any) { + if (err.message === "ARTICLE_NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" }); + next(err); + } + } + + async likeProduct(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const result = await likeService.likeProduct(req.user.id, Number(req.params.id)); + res.status(status.OK).json({ message: "Like toggled", isLiked: result.like }); + } catch (err: any) { + if (err.message === "PRODUCT_NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + next(err); + } + } + + async getLikedArticles(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const likedArticles = await likeService.getLikedArticles(req.user.id); + const articles = likedArticles.map((l) => ({ ...l.article, isLiked: true })); + res.status(status.OK).json(articles); + } catch (err) { + next(err); + } + } + + async getLikedProducts(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const likedProducts = await likeService.getLikedProducts(req.user.id); + const products = likedProducts.map((l) => ({ ...l.product, isLiked: true })); + res.status(status.OK).json(products); + } catch (err) { + next(err); + } + } +} \ No newline at end of file diff --git a/mission 9/src/controllers/photoController.ts b/mission 9/src/controllers/photoController.ts new file mode 100644 index 000000000..405ef1886 --- /dev/null +++ b/mission 9/src/controllers/photoController.ts @@ -0,0 +1,29 @@ +import { Request, Response, NextFunction } from "express"; +import prisma from "../lib/prisma"; +import status from "http-status"; + +export class PhotoController { + async upload(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + + if (!req.file) { + return res.status(status.BAD_REQUEST).json({ message: "No file uploaded" }); + } + + try { + const imageUrl = `/download/${req.file.filename}`; + + const updatedUser = await prisma.user.update({ + where: { id: req.user.id }, + data: { image: imageUrl }, + }); + + res.status(status.OK).json({ + message: "Photo uploaded successfully", + image: updatedUser.image, + }); + } catch (err) { + next(err); + } + } +} \ No newline at end of file diff --git a/mission 9/src/controllers/productController.ts b/mission 9/src/controllers/productController.ts new file mode 100644 index 000000000..5d42d09b9 --- /dev/null +++ b/mission 9/src/controllers/productController.ts @@ -0,0 +1,68 @@ +import { Request, Response, NextFunction } from "express"; +import status from "http-status"; +import { ProductService } from "../services/productService"; +import { ProductCreateSchema, ProductUpdateSchema, ProductQuerySchema } from "../dtos/product.dto"; + +const productService = new ProductService(); + +export class ProductController { + async create(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = ProductCreateSchema.parse(req.body); + const product = await productService.create(req.user.id, parsed); + res.status(status.CREATED).json(product); + } catch (err) { + next(err); + } + } + + async list(req: Request, res: Response, next: NextFunction) { + try { + const parsed = ProductQuerySchema.parse(req.query); + const products = await productService.list(parsed); + res.status(status.OK).json(products); + } catch (err) { + next(err); + } + } + + async detail(req: Request, res: Response, next: NextFunction) { + try { + const productId = Number(req.params.id); + const product = await productService.getDetail(productId); + if (!product) return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + res.status(status.OK).json(product); + } catch (err) { + next(err); + } + } + + async update(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = ProductUpdateSchema.parse(req.body) as { name?: string; description?: string; price?: number; tags?: string; }; + const productId = Number(req.params.id); + const updated = await productService.update(req.user.id, productId, parsed); + + res.status(status.OK).json(updated); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + + async delete(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const productId = Number(req.params.id); + await productService.delete(req.user.id, productId); + res.status(status.NO_CONTENT).end(); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } +} \ No newline at end of file diff --git a/mission 9/src/controllers/userController.ts b/mission 9/src/controllers/userController.ts new file mode 100644 index 000000000..8f706c6b5 --- /dev/null +++ b/mission 9/src/controllers/userController.ts @@ -0,0 +1,96 @@ +import { Request, Response, NextFunction } from "express"; +import status from "http-status"; +import { UserService } from "../services/userService"; +import { setTokenCookies, clearTokenCookies } from "../lib/cookieUtil"; +import { UserRegisterSchema, UserUpdateSchema, UserPasswordSchema, UserLoginSchema } from "../dtos/user.dto"; + +const userService = new UserService(); + +export class UserController { + async register(req: Request, res: Response, next: NextFunction) { + try { + const parsed = UserRegisterSchema.parse(req.body); + const result = await userService.register(parsed); + res.status(status.CREATED).json(result); + } catch (err: any) { + if (err.message === "EMAIL_EXISTS") { + return res.status(status.CONFLICT).json({ message: "This ID already exists" }); + } + next(err); + } + } + + login(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + try { + const { accessToken, refreshToken } = userService.generateUserTokens(req.user.id); + setTokenCookies(res, accessToken, refreshToken); + res.status(status.OK).json({ token: accessToken, refreshToken }); + } catch (err) { + next(err); + } + } + + async profile(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const profile = await userService.getProfile(req.user.id); + res.status(status.OK).json(profile); + } catch (err) { + next(err); + } + } + + async modifyInformation(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const parsed = UserUpdateSchema.parse(req.body); // DTO 검증 + const updatedUser = await userService.updateInformation(req.user.id, parsed.nickname, parsed.image); + + res.status(status.OK).json({ message: "User information updated successfully", user: updatedUser }); + } catch (err: any) { + if (err.message === "NO_DATA") return res.status(status.BAD_REQUEST).json({ message: "No update data provided" }); + next(err); + } + } + + async modifyPassword(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const parsed = UserPasswordSchema.parse(req.body); // DTO 검증 + const result = await userService.updatePassword(req.user.id, parsed); + + res.status(status.OK).json(result); + } catch (err) { + next(err); + } + } + + async products(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const products = await userService.getProducts(req.user.id); + if (!products || products.length === 0) { + return res.status(status.NOT_FOUND).json({ message: "No product" }); + } + res.status(status.OK).json(products); + } catch (err) { + next(err); + } + } + + refreshTokens(req: Request, res: Response) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const { accessToken, refreshToken } = userService.generateUserTokens(req.user.id); + setTokenCookies(res, accessToken, refreshToken); + res.status(status.OK).send({ message: "Tokens refreshed" }); + } + + logout(req: Request, res: Response) { + clearTokenCookies(res); + res.status(status.OK).send({ message: "Logged out successfully" }); + } +} diff --git a/mission 9/src/dtos/article.dto.ts b/mission 9/src/dtos/article.dto.ts new file mode 100644 index 000000000..c6709cf00 --- /dev/null +++ b/mission 9/src/dtos/article.dto.ts @@ -0,0 +1,38 @@ +import { z } from "zod"; + +// CREATE DTO +export const ArticleCreateSchema = z.object({ + title: z.string().min(1, { message: "제목을 입력해주세요" }), + content: z + .string() + .min(10, { message: "내용은 최소 10자 이상이어야 합니다." }) + .max(200, { message: "내용은 최대 200자까지 가능합니다." }), +}); +export type ArticleCreateDTO = z.infer; + +// UPDATE DTO (PATCH) +export const ArticleUpdateSchema = z.object({ + title: z.string().min(1, { message: "제목을 입력해주세요" }).optional(), + content: z + .string() + .min(10, { message: "내용은 최소 10자 이상이어야 합니다." }) + .max(200, { message: "내용은 최대 200자까지 가능합니다." }) + .optional(), +}); +export type ArticleUpdateDTO = z.infer; + +// QUERY DTO (GET /articles) +export const ArticleQuerySchema = z.object({ + page: z + .string() + .default("1") + .transform(Number) + .refine((val) => val > 0, { message: "page는 1 이상의 정수여야 합니다." }), + pageSize: z + .string() + .default("5") + .transform(Number) + .refine((val) => val > 0 && val <= 100, { message: "pageSize는 1~100 사이여야 합니다." }), + keyword: z.string().default(""), +}); +export type ArticleQueryDTO = z.infer; diff --git a/mission 9/src/dtos/product.dto.ts b/mission 9/src/dtos/product.dto.ts new file mode 100644 index 000000000..edac3858a --- /dev/null +++ b/mission 9/src/dtos/product.dto.ts @@ -0,0 +1,28 @@ +import { z } from "zod"; + + +// CREATE DTO +export const ProductCreateSchema = z.object({ + name: z.string().min(1, { message: "이름을 입력해주세요" }), + description: z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }), + price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }), + tags: z.string().default(""), +}); +export type ProductCreateDTO = z.infer; + +// UPDATE DTO +export const ProductUpdateSchema = z.object({ + name: z.string().min(1, { message: "이름을 입력해주세요" }).optional(), + description: z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }).optional(), + price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }).optional(), + tags: z.string().default("").optional(), +}); +export type ProductUpdateDTO = z.infer; + +// QUERY DTO +export const ProductQuerySchema = z.object({ + page: z.string().default("1").transform(Number).refine((v) => v > 0), + pageSize: z.string().default("5").transform(Number).refine((v) => v > 0 && v <= 100), + keyword: z.string().default(""), +}); +export type ProductQueryDTO = z.infer; \ No newline at end of file diff --git a/mission 9/src/dtos/user.dto.ts b/mission 9/src/dtos/user.dto.ts new file mode 100644 index 000000000..1bed9d74a --- /dev/null +++ b/mission 9/src/dtos/user.dto.ts @@ -0,0 +1,29 @@ +import { z } from "zod"; + +// 회원가입 +export const UserRegisterSchema = z.object({ + email: z.string().email({ message: "Invalid email" }), + nickname: z.string().min(2, { message: "Nickname too short" }), + password: z.string().min(6, { message: "Password too short" }), +}); +export type UserRegisterDTO = z.infer; + +// 로그인 +export const UserLoginSchema = z.object({ + email: z.string().email(), + password: z.string().min(6), +}); +export type UserLoginDTO = z.infer; + +// 정보 수정 (PATCH) +export const UserUpdateSchema = z.object({ + nickname: z.string().min(2).optional(), + image: z.string().url().optional(), +}); +export type UserUpdateDTO = z.infer; + +// 비밀번호 수정 +export const UserPasswordSchema = z.object({ + password: z.string().min(6, { message: "Password too short" }), +}); +export type UserPasswordDTO = z.infer; diff --git a/mission 9/src/lib/constants.ts b/mission 9/src/lib/constants.ts new file mode 100644 index 000000000..af8e48a99 --- /dev/null +++ b/mission 9/src/lib/constants.ts @@ -0,0 +1,21 @@ +import dotenv from 'dotenv'; + +dotenv.config(); + +const NODE_ENV = process.env.NODE_ENV || 'development'; +const PORT = process.env.PORT || 3000; +const JWT_ACCESS_TOKEN_SECRET = + process.env.JWT_ACCESS_TOKEN_SECRET || 'your_jwt_access_token_secret'; +const JWT_REFRESH_TOKEN_SECRET = + process.env.JWT_REFRESH_TOKEN_SECRET || 'your_jwt_refresh_token_secret'; +const ACCESS_TOKEN_COOKIE_NAME = 'access-token'; +const REFRESH_TOKEN_COOKIE_NAME = 'refresh-token'; + +export { + NODE_ENV, + PORT, + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, + ACCESS_TOKEN_COOKIE_NAME, + REFRESH_TOKEN_COOKIE_NAME, +}; diff --git a/mission 9/src/lib/cookieUtil.ts b/mission 9/src/lib/cookieUtil.ts new file mode 100644 index 000000000..6d50ff83d --- /dev/null +++ b/mission 9/src/lib/cookieUtil.ts @@ -0,0 +1,22 @@ +import { Response } from "express"; +import { ACCESS_TOKEN_COOKIE_NAME, REFRESH_TOKEN_COOKIE_NAME, NODE_ENV } from "./constants"; + +export function setTokenCookies(res: Response, accessToken: string, refreshToken: string) { + res.cookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, { + httpOnly: true, + secure: NODE_ENV === "production", + maxAge: 1 * 60 * 60 * 1000, // 1시간 + }); + + res.cookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken, { + httpOnly: true, + secure: NODE_ENV === "production", + maxAge: 7 * 24 * 60 * 60 * 1000, // 7일 + path: "/users/refresh", + }); +} + +export function clearTokenCookies(res: Response) { + res.clearCookie(ACCESS_TOKEN_COOKIE_NAME); + res.clearCookie(REFRESH_TOKEN_COOKIE_NAME); +} diff --git a/mission 9/src/lib/passport/index.ts b/mission 9/src/lib/passport/index.ts new file mode 100644 index 000000000..771eb1518 --- /dev/null +++ b/mission 9/src/lib/passport/index.ts @@ -0,0 +1,9 @@ +import passport from 'passport'; +import { localStrategy } from './localStrategy'; +import { accessTokenStrategy, refreshTokenStrategy } from './jwtStrategy'; + +passport.use('local', localStrategy); +passport.use('access-token', accessTokenStrategy); +passport.use('refresh-token', refreshTokenStrategy); + +export default passport; diff --git a/mission 9/src/lib/passport/jwtStrategy.ts b/mission 9/src/lib/passport/jwtStrategy.ts new file mode 100644 index 000000000..7d258318c --- /dev/null +++ b/mission 9/src/lib/passport/jwtStrategy.ts @@ -0,0 +1,45 @@ +import { Strategy as JwtStrategy } from 'passport-jwt'; +import prisma from '../prisma'; +import type { Request } from 'express'; +import type { VerifiedCallback } from 'passport-jwt'; +import { + ACCESS_TOKEN_COOKIE_NAME, + REFRESH_TOKEN_COOKIE_NAME, + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, +} from '../constants'; + +interface JwtPayload { + sub: number; +} + +const accessTokenOptions = { + jwtFromRequest: (req: Request) => req.cookies[ACCESS_TOKEN_COOKIE_NAME], + secretOrKey: JWT_ACCESS_TOKEN_SECRET, +}; + +const refreshTokenOptions = { + jwtFromRequest: (req: Request) => req.cookies[REFRESH_TOKEN_COOKIE_NAME], + secretOrKey: JWT_REFRESH_TOKEN_SECRET, +}; + +async function jwtVerify(payload: JwtPayload, done: VerifiedCallback) { + try { + const user = await prisma.user.findUnique({ + where: { id: payload.sub }, + }); + done(null, user); + } catch (error) { + done(error, false); + } +} + +export const accessTokenStrategy = new JwtStrategy( + accessTokenOptions, + jwtVerify +); + +export const refreshTokenStrategy = new JwtStrategy( + refreshTokenOptions, + jwtVerify +); diff --git a/mission 9/src/lib/passport/localStrategy.ts b/mission 9/src/lib/passport/localStrategy.ts new file mode 100644 index 000000000..3c3e7ba10 --- /dev/null +++ b/mission 9/src/lib/passport/localStrategy.ts @@ -0,0 +1,27 @@ +import { Strategy as LocalStrategy } from "passport-local"; +import bcrypt from "bcrypt"; +import prisma from "../prisma"; + +export const localStrategy = new LocalStrategy( + { + usernameField: "email", // email을 localStrategy의 고정값 'username' 대신 쓰도록 지정 + passwordField: "password", + }, + async (email, password, done) => { + try { + const user = await prisma.user.findUnique({ where: { email } }); + if (!user) { + return done(null, false, { message: "No user found" }); + } + + const isPasswordValid = await bcrypt.compare(password, user.password); + if (!isPasswordValid) { + return done(null, false, { message: "Invalid password" }); + } + + return done(null, user); + } catch (err) { + return done(err); + } + } +); diff --git a/mission 9/src/lib/prisma.ts b/mission 9/src/lib/prisma.ts new file mode 100644 index 000000000..b904402d2 --- /dev/null +++ b/mission 9/src/lib/prisma.ts @@ -0,0 +1,5 @@ +import { PrismaClient } from '@prisma/client'; + +const prisma = new PrismaClient(); + +export default prisma; \ No newline at end of file diff --git a/mission 9/src/lib/token.ts b/mission 9/src/lib/token.ts new file mode 100644 index 000000000..5bdb25906 --- /dev/null +++ b/mission 9/src/lib/token.ts @@ -0,0 +1,27 @@ + import jwt from 'jsonwebtoken'; +import { + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, +} from './constants'; + +function generateTokens(userId: number) { + const accessToken = jwt.sign({ sub: userId }, JWT_ACCESS_TOKEN_SECRET, { + expiresIn: '1h', + }); + const refreshToken = jwt.sign({ sub: userId }, JWT_REFRESH_TOKEN_SECRET, { + expiresIn: '1d', + }); + return { accessToken, refreshToken }; +} + +function verifyAccessToken(token: string) { + const decoded = jwt.verify(token, JWT_ACCESS_TOKEN_SECRET); + return { userId: decoded.sub }; +} + +function verifyRefreshToken(token: string) { + const decoded = jwt.verify(token, JWT_REFRESH_TOKEN_SECRET); + return { userId: decoded.sub }; +} + +export { generateTokens, verifyAccessToken, verifyRefreshToken }; diff --git a/mission 9/src/middlewares/errorHandler.ts b/mission 9/src/middlewares/errorHandler.ts new file mode 100644 index 000000000..dcaa5aaf3 --- /dev/null +++ b/mission 9/src/middlewares/errorHandler.ts @@ -0,0 +1,22 @@ +import { z } from "zod"; +import httpStatus from "http-status"; +import express , { type Request, type Response, type NextFunction } from "express"; + +interface ExtendedError extends Error { + code?: string; +} + +export function errorHandler(err: ExtendedError, req: Request, res: Response, next: NextFunction) { + if (err instanceof z.ZodError) { + return res.status(httpStatus.BAD_REQUEST).json({ error: err.issues }); + } + + if (err.code === "P2025") { + return res.status(httpStatus.NOT_FOUND).json({ error: "Record not found" }); + } + + console.error("unhandled Error:", err); + return res + .status(httpStatus.INTERNAL_SERVER_ERROR) + .json({ error: "Internal Server Error" }); +} diff --git a/mission 9/src/repositories/alertRepository.ts b/mission 9/src/repositories/alertRepository.ts new file mode 100644 index 000000000..71d7bf1e6 --- /dev/null +++ b/mission 9/src/repositories/alertRepository.ts @@ -0,0 +1,27 @@ +import prisma from "../lib/prisma"; + +export class AlertRepository { + async createAlert(data: { userId: number; message: string; link?: string }) { + return prisma.alert.create({ data }); + } + + async findByUserId(userId: number) { + return prisma.alert.findMany({ + where: { userId }, + orderBy: { createdAt: "desc" }, + }); + } + + async markAsRead(id: number) { + return prisma.alert.update({ + where: { id }, + data: { isRead: true }, + }); + } + + async countUnread(userId: number) { + return prisma.alert.count({ + where: { userId, isRead: false }, + }); + } +} diff --git a/mission 9/src/repositories/articleRepository.ts b/mission 9/src/repositories/articleRepository.ts new file mode 100644 index 000000000..815428ffb --- /dev/null +++ b/mission 9/src/repositories/articleRepository.ts @@ -0,0 +1,39 @@ +import prisma from "../lib/prisma"; +import { Prisma } from "@prisma/client"; + +export class ArticleRepository { + async createArticle(data: { userId: number; title: string; content: string }) { + return prisma.article.create({ data }); + } + + async findMany(where: Prisma.ArticleWhereInput, skip: number, take: number) { + return prisma.article.findMany({ + skip, + take, + orderBy: { createdAt: "desc" }, + select: { id: true, title: true, content: true, createdAt: true }, + where, + }); + } + + async findById(id: number) { + return prisma.article.findUnique({ + where: { id }, + select: { id: true, userId: true, title: true, content: true, createdAt: true }, + }); + } + + async updatedArticle(id: number, data: { title?: string; content?: string }) { + const updateData: { title?: string; content?: string } = {}; + if (data.title !== undefined) updateData.title = data.title; + if (data.content !== undefined) updateData.content = data.content; + + return prisma.article.update({ where: { id }, data: updateData }); + } + + async deleteArticle(id: number): Promise { + await prisma.article.delete({ where: { id } }); + } +} + +export default new ArticleRepository(); \ No newline at end of file diff --git a/mission 9/src/repositories/commentRepository.ts b/mission 9/src/repositories/commentRepository.ts new file mode 100644 index 000000000..38de775ae --- /dev/null +++ b/mission 9/src/repositories/commentRepository.ts @@ -0,0 +1,52 @@ +import prisma from "../lib/prisma"; + +export class CommentRepository { + async createProductComment(userId: number, productId: number, content: string) { + return prisma.comment.create({ + data: { content, productId, articleId: null, userId }, + }); + } + + async createArticleComment(userId: number, articleId: number, content: string) { + return prisma.comment.create({ + data: { content, productId: null, articleId, userId }, + }); + } + + async findById(commentId: number) { + return prisma.comment.findUnique({ where: { id: commentId } }); + } + + async updateComment(commentId: number, content: string) { + return prisma.comment.update({ + where: { id: commentId }, + data: { content }, + }); + } + + async deleteComment(commentId: number) { + return prisma.comment.delete({ where: { id: commentId } }); + } + + async findProductComments(productId: number, lastId?: number) { + return prisma.comment.findMany({ + where: { articleId: null, productId }, + take: 5, + skip: lastId ? 1 : 0, + ...(lastId && { cursor: { id: lastId } }), + select: { id: true, content: true, createdAt: true }, + }); + } + + async findArticleComments(articleId: number, lastId?: number) { + return prisma.comment.findMany({ + where: { articleId, productId: null }, + take: 5, + skip: lastId ? 1 : 0, + ...(lastId && { cursor: { id: lastId } }), + select: { id: true, content: true, createdAt: true }, + }); + } +} + +export default new CommentRepository(); \ No newline at end of file diff --git a/mission 9/src/repositories/likeRepository.ts b/mission 9/src/repositories/likeRepository.ts new file mode 100644 index 000000000..37eb13fbf --- /dev/null +++ b/mission 9/src/repositories/likeRepository.ts @@ -0,0 +1,85 @@ +import prisma from "../lib/prisma"; + +export class LikeRepository { + async findArticle(articleId: number) { + return prisma.article.findUnique({ where: { id: articleId } }); + } + + async findProduct(productId: number) { + return prisma.product.findUnique({ where: { id: productId } }); + } + + async findArticleLike(userId: number, articleId: number) { + return prisma.like.findUnique({ + where: { userId_articleId: { userId, articleId } }, + }); + } + + async findProductLike(userId: number, productId: number) { + return prisma.like.findUnique({ + where: { userId_productId: { userId, productId } }, + }); + } + + async toggleArticleLike(userId: number, articleId: number, current: boolean) { + return prisma.like.update({ + where: { userId_articleId: { userId, articleId } }, + data: { like: !current }, + }); + } + + async toggleProductLike(userId: number, productId: number, current: boolean) { + return prisma.like.update({ + where: { userId_productId: { userId, productId } }, + data: { like: !current }, + }); + } + + async createArticleLike(userId: number, articleId: number) { + return prisma.like.create({ + data: { like: true, userId, articleId }, + }); + } + + async createProductLike(userId: number, productId: number) { + return prisma.like.create({ + data: { like: true, userId, productId }, + }); + } + + async findLikedArticles(userId: number) { + return prisma.like.findMany({ + where: { userId, articleId: { not: null }, like: true }, + include: { + article: { select: { id: true, title: true } }, + }, + }); + } + + async findLikedProducts(userId: number) { + return prisma.like.findMany({ + where: { userId, productId: { not: null }, like: true }, + include: { + product: { select: { id: true, name: true, price: true, tags: true } }, + }, + }); + } + + async findUsersWhoLikedProduct(productId: number) { + const likes = await prisma.like.findMany({ + where: { + productId, + like: true, + }, + select: { + user: { + select: { + id: true, + nickname: true, + }, + }, + }, + }); + return likes.map((like) => like.user); + } +} diff --git a/mission 9/src/repositories/productRepository.ts b/mission 9/src/repositories/productRepository.ts new file mode 100644 index 000000000..62b287709 --- /dev/null +++ b/mission 9/src/repositories/productRepository.ts @@ -0,0 +1,49 @@ +import prisma from "../lib/prisma"; +import { Prisma } from "@prisma/client"; +import { ProductCreateDTO, ProductUpdateDTO, ProductQueryDTO } from "../dtos/product.dto"; + +export class ProductRepository { + async createProduct(data: { userId: number; name: string; description: string; price: number; tags: string }) { + return prisma.product.create({ data }); + } + + async findMany(where: Prisma.ProductWhereInput, skip: number, take: number) { + return prisma.product.findMany({ + skip, + take, + orderBy: { createdAt: "desc" }, + select: { + id: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + where, + }); + } + + async findById(id: number) { + return prisma.product.findUnique({ + where: { id }, + select: { + id: true, + userId: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + }); + } + + async updateProduct(id: number, data: Partial<{ name: string; description: string; price: number; tags: string }>) { + return prisma.product.update({ where: { id }, data }); + } + + async deleteProduct(id: number) { + return prisma.product.delete({ where: { id } }); + } +} \ No newline at end of file diff --git a/mission 9/src/repositories/userRepository.ts b/mission 9/src/repositories/userRepository.ts new file mode 100644 index 000000000..e2eb38b76 --- /dev/null +++ b/mission 9/src/repositories/userRepository.ts @@ -0,0 +1,29 @@ +import prisma from "../lib/prisma"; + +export class UserRepository { + async findByEmail(email: string) { + return prisma.user.findUnique({ where: { email } }); + } + + async findById(id: number) { + return prisma.user.findUnique({ + where: { id }, + select: { id: true, email: true, nickname: true, image: true, createdAt: true, updatedAt: true }, + }); + } + + async createUser(email: string, nickname: string, password: string) { + return prisma.user.create({ data: { email, nickname, password } }); + } + + async updateUser(id: number, data: Partial<{ nickname: string; image: string; password: string }>) { + return prisma.user.update({ where: { id }, data }); + } + + async findProductsByUserId(userId: number) { + return prisma.product.findMany({ + where: { userId }, + select: { name: true, description: true, price: true, tags: true }, + }); + } +} \ No newline at end of file diff --git a/mission 9/src/routers/alertRouter.ts b/mission 9/src/routers/alertRouter.ts new file mode 100644 index 000000000..c461c7cb3 --- /dev/null +++ b/mission 9/src/routers/alertRouter.ts @@ -0,0 +1,14 @@ +import express from "express"; +import passport from "../lib/passport"; +import { AlertController } from "../controllers/alertController"; + +const router = express.Router(); +const controller = new AlertController(); + +// 내 알림 조회 +router.get("/", passport.authenticate("access-token", { session: false }), controller.list); + +// 알림 읽음 처리 +router.patch("/:id/read", passport.authenticate("access-token", { session: false }), controller.markAsRead); + +export default router; diff --git a/mission 9/src/routers/articleRouter.ts b/mission 9/src/routers/articleRouter.ts new file mode 100644 index 000000000..4c4161a6b --- /dev/null +++ b/mission 9/src/routers/articleRouter.ts @@ -0,0 +1,14 @@ +import express from "express"; +import passport from "../lib/passport"; +import { ArticleController } from "../controllers/articleController"; + +const router = express.Router(); +const controller = new ArticleController(); + +router.post("/", passport.authenticate("access-token", { session: false }), controller.create); +router.get("/", passport.authenticate("access-token", { session: false }), controller.list); +router.get("/:id", passport.authenticate("access-token", { session: false }), controller.detail); +router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update); +router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete); + +export default router; \ No newline at end of file diff --git a/mission 9/src/routers/commentRouter.ts b/mission 9/src/routers/commentRouter.ts new file mode 100644 index 000000000..f7b6b4903 --- /dev/null +++ b/mission 9/src/routers/commentRouter.ts @@ -0,0 +1,15 @@ +import express from "express"; +import passport from "../lib/passport"; +import { CommentController } from "../controllers/commentController"; + +const router = express.Router(); +const controller = new CommentController(); + +router.post("/products/:id", passport.authenticate("access-token", { session: false }), controller.createProductComment); +router.post("/articles/:id", passport.authenticate("access-token", { session: false }), controller.createArticleComment); +router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.modifyComment); +router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.deleteComment); +router.get("/products/:id", passport.authenticate("access-token", { session: false }), controller.productCommentList); +router.get("/articles/:id", passport.authenticate("access-token", { session: false }), controller.articleCommentList); + +export default router; \ No newline at end of file diff --git a/mission 9/src/routers/index.ts b/mission 9/src/routers/index.ts new file mode 100644 index 000000000..82c6b975b --- /dev/null +++ b/mission 9/src/routers/index.ts @@ -0,0 +1,21 @@ +import express from "express"; + +import userRouter from "./userRouter"; +import articleRouter from "./articleRouter"; +import productRouter from "./productRouter"; +import commentRouter from "./commentRouter"; +import likeRouter from "./likeRouter"; +import photoRouter from "./photoRouter"; // ✅ 공통 업로드 전용 +import alertRouter from "./alertRouter"; + +const router = express.Router(); + +router.use("/users", userRouter); +router.use("/articles", articleRouter); +router.use("/products", productRouter); +router.use("/comments", commentRouter); +router.use("/likes", likeRouter); +router.use(photoRouter); // 📌 prefix는 /photos +router.use("/alerts", alertRouter); + +export default router; \ No newline at end of file diff --git a/mission 9/src/routers/likeRouter.ts b/mission 9/src/routers/likeRouter.ts new file mode 100644 index 000000000..10ec9924d --- /dev/null +++ b/mission 9/src/routers/likeRouter.ts @@ -0,0 +1,13 @@ +import express from "express"; +import passport from "../lib/passport"; +import { LikeController } from "../controllers/likeController"; + +const router = express.Router(); +const controller = new LikeController(); + +router.post("/articles/:id", passport.authenticate("access-token", { session: false }), controller.likeArticle); +router.post("/products/:id", passport.authenticate("access-token", { session: false }), controller.likeProduct); +router.get("/articles", passport.authenticate("access-token", { session: false }), controller.getLikedArticles); +router.get("/products", passport.authenticate("access-token", { session: false }), controller.getLikedProducts); + +export default router; \ No newline at end of file diff --git a/mission 9/src/routers/photoRouter.ts b/mission 9/src/routers/photoRouter.ts new file mode 100644 index 000000000..796ba57b4 --- /dev/null +++ b/mission 9/src/routers/photoRouter.ts @@ -0,0 +1,17 @@ +import express from "express"; +import multer from "multer"; +import passport from "../lib/passport"; +import { PhotoController } from "../controllers/photoController"; + +const router = express.Router(); +const upload = multer({ dest: "uploads/" }); +const controller = new PhotoController(); + +router.post( + "/", + passport.authenticate("access-token", { session: false }), + upload.single("image"), + controller.upload +); + +export default router; diff --git a/mission 9/src/routers/productRouter.ts b/mission 9/src/routers/productRouter.ts new file mode 100644 index 000000000..63f2d5d87 --- /dev/null +++ b/mission 9/src/routers/productRouter.ts @@ -0,0 +1,14 @@ +import express from "express"; +import passport from "../lib/passport"; +import { ProductController } from "../controllers/productController"; + +const router = express.Router(); +const controller = new ProductController(); + +router.post("/", passport.authenticate("access-token", { session: false }), controller.create); +router.get("/", controller.list); +router.get("/:id", passport.authenticate("access-token", { session: false }), controller.list); +router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update); +router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete); + +export default router; \ No newline at end of file diff --git a/mission 9/src/routers/userRouter.ts b/mission 9/src/routers/userRouter.ts new file mode 100644 index 000000000..0df2f4317 --- /dev/null +++ b/mission 9/src/routers/userRouter.ts @@ -0,0 +1,17 @@ +import express from "express"; +import passport from "../lib/passport"; +import { UserController } from "../controllers/userController"; + +const router = express.Router(); +const controller = new UserController(); + +router.post("/register", controller.register); +router.post("/login", passport.authenticate("local", { session: false }), controller.login); +router.get("/profile", passport.authenticate("access-token", { session: false }), controller.profile); +router.patch("/modifyInformation", passport.authenticate("access-token", { session: false }), controller.modifyInformation); +router.patch("/modifyPassword", passport.authenticate("access-token", { session: false }), controller.modifyPassword); +router.get("/products", passport.authenticate("access-token", { session: false }), controller.products); +router.post("/refresh", passport.authenticate("refresh-token", { session: false }), controller.refreshTokens); +router.post("/logout", controller.logout); + +export default router; diff --git a/mission 9/src/services/alertService.ts b/mission 9/src/services/alertService.ts new file mode 100644 index 000000000..b9d89c23f --- /dev/null +++ b/mission 9/src/services/alertService.ts @@ -0,0 +1,26 @@ +import { AlertRepository } from "../repositories/alertRepository"; +import { io } from "../app"; + +export class AlertService { + private repo = new AlertRepository(); + + async create(userId: number, message: string, link?: string) { + const alert = await this.repo.createAlert({ userId, message, link }); + + io.to(`user:${userId}`).emit("newAlert", alert); + + return alert; + } + + async list(userId: number) { + return this.repo.findByUserId(userId); + } + + async read(alertId: number) { + return this.repo.markAsRead(alertId); + } + + async countUnread(userId: number) { + return this.repo.countUnread(userId); + } +} diff --git a/mission 9/src/services/articleService.ts b/mission 9/src/services/articleService.ts new file mode 100644 index 000000000..885446aa9 --- /dev/null +++ b/mission 9/src/services/articleService.ts @@ -0,0 +1,46 @@ +import { ArticleRepository } from "../repositories/articleRepository"; +import type { ArticleCreateDTO, ArticleUpdateDTO, ArticleQueryDTO } from "../dtos/article.dto"; +import type { Prisma } from "@prisma/client"; + +export class ArticleService { + private repo = new ArticleRepository(); + + async create(userId: number, data: ArticleCreateDTO) { + return this.repo.createArticle({ ...data, userId }); + } + + async list({ page, pageSize, keyword }: ArticleQueryDTO) { + const where: Prisma.ArticleWhereInput = keyword + ? { + OR: [ + { title: { contains: keyword, mode: "insensitive" } }, + { content: { contains: keyword, mode: "insensitive" } }, + ], + } + : {}; + + return this.repo.findMany(where, (page - 1) * pageSize, pageSize); + } + + async getDetail(id: number) { + return this.repo.findById(id); + } + + async update(userId: number, data: ArticleUpdateDTO, articleId: number) { + const article = await this.repo.findById(articleId); + if (!article) throw new Error("NOT_FOUND"); + if (article.userId !== userId) throw new Error("FORBIDDEN"); + + return this.repo.updatedArticle(articleId, data); + } + + async delete(userId: number, articleId: number) { + const article = await this.repo.findById(articleId); + if (!article) throw new Error("NOT_FOUND"); + if (article.userId !== userId) throw new Error("FORBIDDEN"); + + await this.repo.deleteArticle(articleId); + } +} + +export default new ArticleService(); \ No newline at end of file diff --git a/mission 9/src/services/commentService.ts b/mission 9/src/services/commentService.ts new file mode 100644 index 000000000..e3eb961b5 --- /dev/null +++ b/mission 9/src/services/commentService.ts @@ -0,0 +1,79 @@ +import { CommentRepository } from "../repositories/commentRepository"; +import { ArticleRepository } from "../repositories/articleRepository"; +import { ProductRepository } from "../repositories/productRepository"; +import { AlertService } from "../services/alertService"; + +export class CommentService { + private repo = new CommentRepository(); + private articleRepo = new ArticleRepository(); + private productRepo = new ProductRepository(); + private alertService = new AlertService(); + + async createArticleComment( + userId: number, + articleId: number, + content: string + ) { + const comment = await this.repo.createArticleComment( + userId, + articleId, + content + ); + const article = await this.articleRepo.findById(articleId); + + if (article && article.userId !== userId) { + await this.alertService.create( + article.userId, + "내 게시글에 새로운 댓글이 달렸습니다.", + `/articles/${articleId}` + ); + } + + return comment; + } + + async createProductComment( + userId: number, + productId: number, + content: string + ) { + const comment = await this.repo.createProductComment( + userId, + productId, + content + ); + const product = await this.productRepo.findById(productId); + + if (product && product.userId !== userId) { + await this.alertService.create( + product.userId, + "내 판매글에 새로운 댓글이 달렸습니다.", + `/products/${productId}` + ); + } + + return comment; + } + + async updateComment(userId: number, commentId: number, content: string) { + const comment = await this.repo.findById(commentId); + if (!comment) throw new Error("NOT_FOUND"); + if (comment.userId !== userId) throw new Error("FORBIDDEN"); + return this.repo.updateComment(commentId, content); + } + + async deleteComment(userId: number, commentId: number) { + const comment = await this.repo.findById(commentId); + if (!comment) throw new Error("NOT_FOUND"); + if (comment.userId !== userId) throw new Error("FORBIDDEN"); + await this.repo.deleteComment(commentId); + } + + async getProductComments(productId: number, lastId?: number) { + return this.repo.findProductComments(productId, lastId); + } + + async getArticleComments(articleId: number, lastId?: number) { + return this.repo.findArticleComments(articleId, lastId); + } +} diff --git a/mission 9/src/services/likeService.ts b/mission 9/src/services/likeService.ts new file mode 100644 index 000000000..4f7118e7f --- /dev/null +++ b/mission 9/src/services/likeService.ts @@ -0,0 +1,35 @@ +import { LikeRepository } from "../repositories/likeRepository"; + +export class LikeService { + private repo = new LikeRepository(); + + async likeArticle(userId: number, articleId: number) { + const article = await this.repo.findArticle(articleId); + if (!article) throw new Error("ARTICLE_NOT_FOUND"); + + const existing = await this.repo.findArticleLike(userId, articleId); + if (existing) { + return this.repo.toggleArticleLike(userId, articleId, existing.like); + } + return this.repo.createArticleLike(userId, articleId); + } + + async likeProduct(userId: number, productId: number) { + const product = await this.repo.findProduct(productId); + if (!product) throw new Error("PRODUCT_NOT_FOUND"); + + const existing = await this.repo.findProductLike(userId, productId); + if (existing) { + return this.repo.toggleProductLike(userId, productId, existing.like); + } + return this.repo.createProductLike(userId, productId); + } + + async getLikedArticles(userId: number) { + return this.repo.findLikedArticles(userId); + } + + async getLikedProducts(userId: number) { + return this.repo.findLikedProducts(userId); + } +} \ No newline at end of file diff --git a/mission 9/src/services/productService.ts b/mission 9/src/services/productService.ts new file mode 100644 index 000000000..0b2890163 --- /dev/null +++ b/mission 9/src/services/productService.ts @@ -0,0 +1,68 @@ +import { ProductRepository } from "../repositories/productRepository"; +import { LikeRepository } from "../repositories/likeRepository"; +import { AlertService } from "../services/alertService"; +import type { ProductCreateDTO, ProductQueryDTO } from "../dtos/product.dto"; +import type { Prisma } from "@prisma/client"; + +export class ProductService { + private repo = new ProductRepository(); + private likeRepo = new LikeRepository(); + private alertService = new AlertService(); + + async create(userId: number, data: ProductCreateDTO) { + return this.repo.createProduct({ ...data, userId }); + } + + async list({ page, pageSize, keyword }: ProductQueryDTO) { + const where: Prisma.ProductWhereInput = keyword + ? { + OR: [ + { name: { contains: keyword, mode: "insensitive" } }, + { description: { contains: keyword, mode: "insensitive" } }, + ], + } + : {}; + return this.repo.findMany(where, (page - 1) * pageSize, pageSize); + } + + async getDetail(id: number) { + return this.repo.findById(id); + } + + async update( + userId: number, + productId: number, + data: { name?: string; description?: string; price?: number; tags?: string } + ) { + const product = await this.repo.findById(productId); + if (!product) throw new Error("NOT_FOUND"); + if (product.userId !== userId) throw new Error("FORBIDDEN"); + + const oldPrice = product.price; + const updated = await this.repo.updateProduct(productId, data); + + if (data.price !== undefined && data.price !== oldPrice) { + const likedUsers = await this.likeRepo.findUsersWhoLikedProduct(productId); + + const targetUsers = likedUsers.filter((u) => u.id !== userId); + + for (const user of targetUsers) { + await this.alertService.create( + user.id, + `좋아요한 상품 "${product.name}"의 가격이 ${oldPrice}원 → ${data.price}원으로 변경되었습니다.`, + `/products/${productId}` + ); + } + } + + return updated; + } + + async delete(userId: number, productId: number) { + const product = await this.repo.findById(productId); + if (!product) throw new Error("NOT_FOUND"); + if (product.userId !== userId) throw new Error("FORBIDDEN"); + + await this.repo.deleteProduct(productId); + } +} diff --git a/mission 9/src/services/userService.ts b/mission 9/src/services/userService.ts new file mode 100644 index 000000000..f9bd91fc2 --- /dev/null +++ b/mission 9/src/services/userService.ts @@ -0,0 +1,48 @@ +import bcrypt from "bcrypt"; +import { UserRepository } from "../repositories/userRepository"; +import { generateTokens } from "../lib/token"; +import type { UserRegisterDTO, UserUpdateDTO, UserPasswordDTO } from "../dtos/user.dto"; + +export class UserService { + private userRepo = new UserRepository(); + + async register(data: UserRegisterDTO) { + const exists = await this.userRepo.findByEmail(data.email); + if (exists) throw new Error("EMAIL_EXISTS"); + + const salt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(data.password, salt); + + await this.userRepo.createUser(data.email, data.nickname, hashedPassword); + return { message: "User registered successfully" }; + } + + async getProfile(userId: number) { + return this.userRepo.findById(userId); + } + + async updateInformation(userId: number, nickname?: string, image?: string) { + const updateData: Record = {}; + if (nickname) updateData.nickname = nickname; + if (image) updateData.image = image; + + if (Object.keys(updateData).length === 0) throw new Error("NO_DATA"); + + return this.userRepo.updateUser(userId, updateData); + } + + async updatePassword(userId: number, data: UserPasswordDTO) { + const salt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(data.password, salt); + await this.userRepo.updateUser(userId, { password: hashedPassword }); + return { message: "Password updated successfully" }; + } + + async getProducts(userId: number) { + return this.userRepo.findProductsByUserId(userId); + } + + generateUserTokens(userId: number) { + return generateTokens(userId); + } +} diff --git a/mission 9/src/socket.ts b/mission 9/src/socket.ts new file mode 100644 index 000000000..087568b1f --- /dev/null +++ b/mission 9/src/socket.ts @@ -0,0 +1,16 @@ +import { Server } from "socket.io"; + +export function registerSocket(io: Server) { + io.on("connection", (socket) => { + console.log("New client connected:", socket.id); + + socket.on("register", (userId: number) => { + socket.join(`user:${userId}`); + console.log(`User ${userId} joined room user:${userId}`); + }); + + socket.on("disconnect", () => { + console.log("Client disconnected:", socket.id); + }); + }); +} \ No newline at end of file diff --git a/mission 9/src/types/express.d.ts b/mission 9/src/types/express.d.ts new file mode 100644 index 000000000..6f994ace7 --- /dev/null +++ b/mission 9/src/types/express.d.ts @@ -0,0 +1,11 @@ +import type { User as PrismaUser } from "@prisma/client"; + +declare global { + namespace Express { + // Passport req.user 타입을 Prisma User로 확장 + interface User extends PrismaUser {} + } +} + +// 반드시 export {} 필요 +export {}; \ No newline at end of file diff --git a/mission 9/test.http b/mission 9/test.http new file mode 100644 index 000000000..cc1f46c72 --- /dev/null +++ b/mission 9/test.http @@ -0,0 +1,36 @@ +curl -X POST \ + -H "Content-Type: application/json" \ + -d '{"email": "test@example.com", "nickname": "test", "password": "password123"}' \ + http://localhost:3000/users/register + +### + curl -X POST \ + -H "Content-Type: application/json" \ + -d '{"email": "test@example.com", "password": "password123"}' \ + "http://localhost:3000/users/login" + +### + curl -X POST \ +-H "Content-Type: application/json" \ +-b "access-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsImlhdCI6MTc2MjIzMzM2MSwiZXhwIjoxNzYyMjM2OTYxfQ.NND1H5Wao2Gq_yYZz31bLtzEw9AaEGNMgD8RE-8bGKU" \ +-d '{ "title": "테스트", "content": "테스트테스트테스트테스트"}' \ +"http://localhost:3000/articles" + +### + curl -X POST \ +-H "Content-Type: application/json" \ +-b "access-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsImlhdCI6MTc2MjIzMzM2MSwiZXhwIjoxNzYyMjM2OTYxfQ.NND1H5Wao2Gq_yYZz31bLtzEw9AaEGNMgD8RE-8bGKU" \ +-d '{ "content": "덧글 테스트"}' \ +"http://localhost:3000/comments/articles/1" + +### + curl -X GET \ +-H "Content-Type: application/json" \ +-b "access-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsImlhdCI6MTc2MjI0MzQ0MiwiZXhwIjoxNzYyMjQ3MDQyfQ.kGHITSzklAyDEVQWxMZlIlUdwrcy76-UB-t_qXLySto" \ +"http://localhost:3000/comments/articles/1" + +### + curl -X GET \ +-H "Content-Type: application/json" \ +-b "access-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsImlhdCI6MTc2MjI0MzQ0MiwiZXhwIjoxNzYyMjQ3MDQyfQ.kGHITSzklAyDEVQWxMZlIlUdwrcy76-UB-t_qXLySto" \ +"http://localhost:3000/alerts/1" \ No newline at end of file diff --git a/mission 9/test/articleService.test.ts b/mission 9/test/articleService.test.ts new file mode 100644 index 000000000..230de9b9d --- /dev/null +++ b/mission 9/test/articleService.test.ts @@ -0,0 +1,125 @@ +// mock 선언은 import보다 위에 있어야 함 +jest.mock("../src/repositories/articleRepository", () => { + return { + ArticleRepository: jest.fn().mockImplementation(() => ({ + createArticle: jest.fn(), + findMany: jest.fn(), + findById: jest.fn(), + updatedArticle: jest.fn(), + deleteArticle: jest.fn(), + })), + }; +}); + +import articleService, { ArticleService } from "../src/services/articleService"; +import { ArticleRepository } from "../src/repositories/articleRepository"; + +// 타입 추론을 위해 any 대신 명시적 타입 사용 +const repoMock = new ArticleRepository() as jest.Mocked; + +describe("ArticleService", () => { + const mockArticle = { + id: 1, + userId: 1, + title: "테스트 제목", + content: "테스트 내용", + createdAt: new Date(), + updatedAt: new Date(), + }; + + beforeEach(() => { + jest.clearAllMocks(); + // articleService 내부 repo를 mock으로 덮어씀 + (articleService as any).repo = repoMock; + }); + + it("should create an article", async () => { + repoMock.createArticle.mockResolvedValue(mockArticle); + + const result = await articleService.create(1, { + title: "테스트 제목", + content: "테스트 내용", + }); + + expect(result).toEqual(mockArticle); + expect(repoMock.createArticle).toHaveBeenCalledWith({ + title: "테스트 제목", + content: "테스트 내용", + userId: 1, + }); + }); + + it("should list articles with pagination and keyword", async () => { + repoMock.findMany.mockResolvedValue([mockArticle]); + + const result = await articleService.list({ + page: 1, + pageSize: 10, + keyword: "테스트", + }); + + expect(result).toEqual([mockArticle]); + expect(repoMock.findMany).toHaveBeenCalled(); + }); + + it("should get detail of an article", async () => { + repoMock.findById.mockResolvedValue(mockArticle); + + const result = await articleService.getDetail(1); + + expect(result).toEqual(mockArticle); + expect(repoMock.findById).toHaveBeenCalledWith(1); + }); + + it("should update article if user owns it", async () => { + repoMock.findById.mockResolvedValue(mockArticle); + repoMock.updatedArticle.mockResolvedValue({ + ...mockArticle, + title: "수정된 제목", + }); + + const result = await articleService.update(1, { title: "수정된 제목" }, 1); + + expect(result.title).toBe("수정된 제목"); + expect(repoMock.updatedArticle).toHaveBeenCalledWith(1, { + title: "수정된 제목", + }); + }); + + it("should throw FORBIDDEN if another user tries to update", async () => { + repoMock.findById.mockResolvedValue({ ...mockArticle, userId: 999 }); + + await expect( + articleService.update(1, { title: "수정된 제목" }, 1) + ).rejects.toThrow("FORBIDDEN"); + }); + + it("should throw NOT_FOUND if article does not exist on update", async () => { + repoMock.findById.mockResolvedValue(null); + + await expect( + articleService.update(1, { title: "없는 글" }, 1) + ).rejects.toThrow("NOT_FOUND"); + }); + + it("should delete article if user owns it", async () => { + repoMock.findById.mockResolvedValue(mockArticle); + repoMock.deleteArticle.mockResolvedValue(undefined); + + await articleService.delete(1, 1); + + expect(repoMock.deleteArticle).toHaveBeenCalledWith(1); + }); + + it("should throw FORBIDDEN if another user tries to delete", async () => { + repoMock.findById.mockResolvedValue({ ...mockArticle, userId: 999 }); + + await expect(articleService.delete(1, 1)).rejects.toThrow("FORBIDDEN"); + }); + + it("should throw NOT_FOUND if article not found on delete", async () => { + repoMock.findById.mockResolvedValue(null); + + await expect(articleService.delete(1, 1)).rejects.toThrow("NOT_FOUND"); + }); +}); diff --git a/mission 9/test/commentService.test.ts b/mission 9/test/commentService.test.ts new file mode 100644 index 000000000..bff9f6120 --- /dev/null +++ b/mission 9/test/commentService.test.ts @@ -0,0 +1,203 @@ +// --- mock setup (import보다 위에 위치해야 함) --- +jest.mock("../src/repositories/commentRepository", () => ({ + CommentRepository: jest.fn().mockImplementation(() => ({ + createArticleComment: jest.fn(), + createProductComment: jest.fn(), + findById: jest.fn(), + updateComment: jest.fn(), + deleteComment: jest.fn(), + findProductComments: jest.fn(), + findArticleComments: jest.fn(), + })), +})); + +jest.mock("../src/repositories/articleRepository", () => ({ + ArticleRepository: jest.fn().mockImplementation(() => ({ + findById: jest.fn(), + })), +})); + +jest.mock("../src/repositories/productRepository", () => ({ + ProductRepository: jest.fn().mockImplementation(() => ({ + findById: jest.fn(), + })), +})); + +jest.mock("../src/services/alertService", () => ({ + AlertService: jest.fn().mockImplementation(() => ({ + create: jest.fn(), + })), +})); + +// --- imports --- +import { CommentService } from "../src/services/commentService"; +import { CommentRepository } from "../src/repositories/commentRepository"; +import { ArticleRepository } from "../src/repositories/articleRepository"; +import { ProductRepository } from "../src/repositories/productRepository"; +import { AlertService } from "../src/services/alertService"; + +// --- mocks --- +const commentRepoMock = new CommentRepository() as jest.Mocked; +const articleRepoMock = new ArticleRepository() as jest.Mocked; +const productRepoMock = new ProductRepository() as jest.Mocked; +const alertServiceMock = new AlertService() as jest.Mocked; + +describe("CommentService", () => { + let service: CommentService; + + const mockComment = { + id: 1, + userId: 1, + content: "테스트 댓글", + articleId: 1, + productId: null, + createdAt: new Date(), + }; + + const mockArticle = { + id: 1, + userId: 2, + title: "게시글 제목", + content: "내용", + createdAt: new Date(), + updatedAt: new Date(), + }; + + const mockProduct = { + id: 1, + userId: 2, + name: "상품 이름", + description: "상품 설명", + price: 1000, + tags: null, + createdAt: new Date(), + updatedAt: new Date(), + }; + + beforeEach(() => { + jest.clearAllMocks(); + service = new CommentService(); + + // service 내부 repo 교체 + (service as any).repo = commentRepoMock; + (service as any).articleRepo = articleRepoMock; + (service as any).productRepo = productRepoMock; + (service as any).alertService = alertServiceMock; + }); + + // ✅ Article 댓글 생성 테스트 + it("should create article comment and trigger alert to article owner", async () => { + commentRepoMock.createArticleComment.mockResolvedValue(mockComment); + articleRepoMock.findById.mockResolvedValue(mockArticle); + + const result = await service.createArticleComment(1, 1, "테스트 댓글"); + + expect(result).toEqual(mockComment); + expect(commentRepoMock.createArticleComment).toHaveBeenCalledWith(1, 1, "테스트 댓글"); + expect(alertServiceMock.create).toHaveBeenCalledWith( + 2, + "내 게시글에 새로운 댓글이 달렸습니다.", + "/articles/1" + ); + }); + + it("should not trigger alert if commenter is article owner", async () => { + articleRepoMock.findById.mockResolvedValue({ ...mockArticle, userId: 1 }); + commentRepoMock.createArticleComment.mockResolvedValue(mockComment); + + await service.createArticleComment(1, 1, "테스트 댓글"); + + expect(alertServiceMock.create).not.toHaveBeenCalled(); + }); + + // ✅ Product 댓글 생성 테스트 + it("should create product comment and trigger alert to product owner", async () => { + commentRepoMock.createProductComment.mockResolvedValue(mockComment); + productRepoMock.findById.mockResolvedValue(mockProduct); + + const result = await service.createProductComment(1, 1, "테스트 댓글"); + + expect(result).toEqual(mockComment); + expect(alertServiceMock.create).toHaveBeenCalledWith( + 2, + "내 판매글에 새로운 댓글이 달렸습니다.", + "/products/1" + ); + }); + + it("should not trigger alert if commenter is product owner", async () => { + productRepoMock.findById.mockResolvedValue({ ...mockProduct, userId: 1 }); + commentRepoMock.createProductComment.mockResolvedValue(mockComment); + + await service.createProductComment(1, 1, "테스트 댓글"); + + expect(alertServiceMock.create).not.toHaveBeenCalled(); + }); + + // ✅ 댓글 수정 테스트 + it("should update comment if user owns it", async () => { + commentRepoMock.findById.mockResolvedValue(mockComment); + commentRepoMock.updateComment.mockResolvedValue({ + ...mockComment, + content: "수정된 댓글", + }); + + const result = await service.updateComment(1, 1, "수정된 댓글"); + + expect(result.content).toBe("수정된 댓글"); + expect(commentRepoMock.updateComment).toHaveBeenCalledWith(1, "수정된 댓글"); + }); + + it("should throw FORBIDDEN if another user tries to update", async () => { + commentRepoMock.findById.mockResolvedValue({ ...mockComment, userId: 999 }); + + await expect(service.updateComment(1, 1, "수정된 댓글")).rejects.toThrow("FORBIDDEN"); + }); + + it("should throw NOT_FOUND if comment does not exist on update", async () => { + commentRepoMock.findById.mockResolvedValue(null); + + await expect(service.updateComment(1, 1, "없음")).rejects.toThrow("NOT_FOUND"); + }); + + // ✅ 댓글 삭제 테스트 + it("should delete comment if user owns it", async () => { + commentRepoMock.findById.mockResolvedValue(mockComment); + commentRepoMock.deleteComment.mockResolvedValue(undefined as any); + + await service.deleteComment(1, 1); + + expect(commentRepoMock.deleteComment).toHaveBeenCalledWith(1); + }); + + it("should throw FORBIDDEN if another user tries to delete", async () => { + commentRepoMock.findById.mockResolvedValue({ ...mockComment, userId: 999 }); + + await expect(service.deleteComment(1, 1)).rejects.toThrow("FORBIDDEN"); + }); + + it("should throw NOT_FOUND if comment not found on delete", async () => { + commentRepoMock.findById.mockResolvedValue(null); + + await expect(service.deleteComment(1, 1)).rejects.toThrow("NOT_FOUND"); + }); + + // ✅ 댓글 목록 조회 테스트 + it("should get product comments", async () => { + commentRepoMock.findProductComments.mockResolvedValue([mockComment]); + + const result = await service.getProductComments(1); + + expect(result).toEqual([mockComment]); + expect(commentRepoMock.findProductComments).toHaveBeenCalledWith(1, undefined); + }); + + it("should get article comments", async () => { + commentRepoMock.findArticleComments.mockResolvedValue([mockComment]); + + const result = await service.getArticleComments(1); + + expect(result).toEqual([mockComment]); + expect(commentRepoMock.findArticleComments).toHaveBeenCalledWith(1, undefined); + }); +}); diff --git a/mission 9/test/hello.test.ts b/mission 9/test/hello.test.ts new file mode 100644 index 000000000..fe78c37be --- /dev/null +++ b/mission 9/test/hello.test.ts @@ -0,0 +1,4 @@ +test('안녕 Jest', () => { + const value = 'Hello Jest'; + expect(value).toEqual('Hello Jest'); +}); \ No newline at end of file diff --git a/mission 9/test/productService.test.ts b/mission 9/test/productService.test.ts new file mode 100644 index 000000000..f8fb8e36a --- /dev/null +++ b/mission 9/test/productService.test.ts @@ -0,0 +1,121 @@ +// ✅ 1. 반드시 import보다 위에 있어야 함 +jest.mock("../src/repositories/productRepository", () => { + return { + ProductRepository: jest.fn().mockImplementation(() => ({ + createProduct: jest.fn(), + findMany: jest.fn(), + findById: jest.fn(), + updateProduct: jest.fn(), + deleteProduct: jest.fn(), + })), + }; +}); + +import { ProductService } from "../src/services/productService"; +import { ProductRepository } from "../src/repositories/productRepository"; + +describe("ProductService", () => { + let service: ProductService; + let repoMock: jest.Mocked; + + const mockProduct = { + id: 1, + name: "Laptop", + description: "Fast laptop", + price: 2000, + tags: "tech", + userId: 10, + createdAt: new Date(), + updatedAt: new Date(), + }; + + beforeEach(() => { + jest.clearAllMocks(); + service = new ProductService(); + repoMock = service["repo"] as jest.Mocked; + }); + + // ✅ create + it("should create a new product", async () => { + const input = { name: "Phone", description: "Smartphone", price: 1000, tags: "mobile" }; + const created = { ...mockProduct, ...input, id: 2 }; + repoMock.createProduct.mockResolvedValue(created as any); + + const result = await service.create(10, input); + + expect(repoMock.createProduct).toHaveBeenCalledWith({ ...input, userId: 10 }); + expect(result).toEqual(created); + }); + + // ✅ list + it("should list products with keyword filter", async () => { + repoMock.findMany.mockResolvedValue([mockProduct] as any); + + const result = await service.list({ page: 1, pageSize: 10, keyword: "Laptop" }); + + expect(repoMock.findMany).toHaveBeenCalled(); + expect(result).toEqual([mockProduct]); + }); + + // ✅ getDetail + it("should get product detail", async () => { + repoMock.findById.mockResolvedValue(mockProduct as any); + + const result = await service.getDetail(1); + + expect(repoMock.findById).toHaveBeenCalledWith(1); + expect(result).toEqual(mockProduct); + }); + + // ✅ update - success + it("should update product if user owns it", async () => { + repoMock.findById.mockResolvedValue(mockProduct as any); + const updated = { ...mockProduct, name: "Updated Laptop" }; + repoMock.updateProduct.mockResolvedValue(updated as any); + + const result = await service.update(10, 1, { name: "Updated Laptop" }); + + expect(repoMock.findById).toHaveBeenCalledWith(1); + expect(repoMock.updateProduct).toHaveBeenCalledWith(1, { name: "Updated Laptop" }); + expect(result).toEqual(updated); + }); + + // ✅ update - not found + it("should throw NOT_FOUND when product not found", async () => { + repoMock.findById.mockResolvedValue(null); + + await expect(service.update(10, 1, { name: "Updated" })).rejects.toThrow("NOT_FOUND"); + }); + + // ✅ update - forbidden + it("should throw FORBIDDEN when user does not own product", async () => { + repoMock.findById.mockResolvedValue({ ...mockProduct, userId: 99 } as any); + + await expect(service.update(10, 1, { name: "Updated" })).rejects.toThrow("FORBIDDEN"); + }); + + // ✅ delete - success + it("should delete product if user owns it", async () => { + repoMock.findById.mockResolvedValue(mockProduct as any); + repoMock.deleteProduct.mockResolvedValue(undefined as any); + + await service.delete(10, 1); + + expect(repoMock.findById).toHaveBeenCalledWith(1); + expect(repoMock.deleteProduct).toHaveBeenCalledWith(1); + }); + + // ✅ delete - not found + it("should throw NOT_FOUND if product does not exist", async () => { + repoMock.findById.mockResolvedValue(null); + + await expect(service.delete(10, 1)).rejects.toThrow("NOT_FOUND"); + }); + + // ✅ delete - forbidden + it("should throw FORBIDDEN if user does not own product", async () => { + repoMock.findById.mockResolvedValue({ ...mockProduct, userId: 99 } as any); + + await expect(service.delete(10, 1)).rejects.toThrow("FORBIDDEN"); + }); +}); diff --git a/mission 9/tsconfig.json b/mission 9/tsconfig.json new file mode 100644 index 000000000..f052e7e3b --- /dev/null +++ b/mission 9/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + /* ----- 기본 옵션 ----- */ + "target": "ES2020", // 어떤 버전의 JavaScript로 컴파일할지 (ES2020은 최신 Node.js와 호환성이 좋음) + "module": "commonjs", // Node.js 환경에서 사용하는 모듈 시스템 + "rootDir": "./src", // 타입스크립트 소스코드의 루트 폴더 + "outDir": "./dist", // 컴파일된 JavaScript 파일이 저장될 폴더 + + /* ----- 엄격한 타입 검사 옵션 (강력 추천) ----- */ + "strict": true, // 모든 엄격한 타입 검사 옵션을 활성화 (가장 중요!) + "noImplicitAny": true, // 'any' 타입을 명시적으로 사용하지 않으면 에러 발생 + + /* ----- 모듈 관련 옵션 ----- */ + "moduleResolution": "node", // 모듈 해석 방식을 Node.js 스타일로 설정 + "esModuleInterop": true, // CommonJS 모듈을 ES 모듈 방식으로 'import' 할 수 있게 해줌 (예: import express from 'express') + "resolveJsonModule": true, // .json 파일을 모듈처럼 import 할 수 있게 허용 + + /* ----- 추가 옵션 ----- */ + "sourceMap": true, // .map 파일을 생성하여, 디버깅 시 ts 코드를 볼 수 있게 함 + "forceConsistentCasingInFileNames": true, // 파일 이름의 대소문자를 구분하도록 강제 + "skipLibCheck": true, // 의존하는 라이브러리(*.d.ts)의 타입 검사를 건너뛰어 컴파일 속도 향상 + "typeRoots": ["./node_modules/@types", "./src/types"] + }, + "include": ["src/**/*"], // 컴파일할 파일 범위 (src 폴더 아래의 모든 파일) + "exclude": ["node_modules", "dist"], // 컴파일에서 제외할 폴더 + "ts-node": { + "files": true + } +} From e6f0bee65b5cb55bf037b88cf44e1b9ef01881f6 Mon Sep 17 00:00:00 2001 From: Batur-s Date: Fri, 14 Nov 2025 13:27:32 +0900 Subject: [PATCH 31/38] [feat] add test --- mission 9/coverage/clover.xml | 815 +++++++++ mission 9/coverage/coverage-final.json | 42 + mission 9/coverage/lcov-report/base.css | 224 +++ .../coverage/lcov-report/block-navigation.js | 87 + mission 9/coverage/lcov-report/favicon.png | Bin 0 -> 445 bytes mission 9/coverage/lcov-report/index.html | 266 +++ mission 9/coverage/lcov-report/prettify.css | 1 + mission 9/coverage/lcov-report/prettify.js | 2 + .../lcov-report/sort-arrow-sprite.png | Bin 0 -> 138 bytes mission 9/coverage/lcov-report/sorter.js | 210 +++ .../coverage/lcov-report/src/app.ts.html | 205 +++ .../src/controllers/alertController.ts.html | 193 +++ .../src/controllers/articleController.ts.html | 295 ++++ .../src/controllers/commentController.ts.html | 346 ++++ .../lcov-report/src/controllers/index.html | 206 +++ .../src/controllers/likeController.ts.html | 235 +++ .../src/controllers/photoController.ts.html | 169 ++ .../src/controllers/productController.ts.html | 286 ++++ .../src/controllers/userController.ts.html | 376 ++++ .../lcov-report/src/dtos/article.dto.ts.html | 199 +++ .../coverage/lcov-report/src/dtos/index.html | 146 ++ .../lcov-report/src/dtos/product.dto.ts.html | 166 ++ .../lcov-report/src/dtos/user.dto.ts.html | 172 ++ mission 9/coverage/lcov-report/src/index.html | 116 ++ .../lcov-report/src/lib/constants.ts.html | 148 ++ .../lcov-report/src/lib/cookieUtil.ts.html | 151 ++ .../coverage/lcov-report/src/lib/index.html | 161 ++ .../lcov-report/src/lib/passport/index.html | 146 ++ .../src/lib/passport/index.ts.html | 112 ++ .../src/lib/passport/jwtStrategy.ts.html | 241 +++ .../src/lib/passport/localStrategy.ts.html | 166 ++ .../lcov-report/src/lib/prisma.ts.html | 97 ++ .../lcov-report/src/lib/token.ts.html | 166 ++ .../src/middlewares/errorHandler.ts.html | 151 ++ .../lcov-report/src/middlewares/index.html | 116 ++ .../src/repositories/alertRepository.ts.html | 184 ++ .../repositories/articleRepository.ts.html | 199 +++ .../repositories/commentRepository.ts.html | 238 +++ .../lcov-report/src/repositories/index.html | 191 +++ .../src/repositories/likeRepository.ts.html | 340 ++++ .../repositories/productRepository.ts.html | 229 +++ .../src/repositories/userRepository.ts.html | 169 ++ .../src/routers/alertRouter.ts.html | 121 ++ .../src/routers/articleRouter.ts.html | 130 ++ .../src/routers/commentRouter.ts.html | 139 ++ .../lcov-report/src/routers/index.html | 221 +++ .../lcov-report/src/routers/index.ts.html | 145 ++ .../src/routers/likeRouter.ts.html | 121 ++ .../src/routers/photoRouter.ts.html | 136 ++ .../src/routers/productRouter.ts.html | 136 ++ .../src/routers/userRouter.ts.html | 136 ++ .../src/services/alertService.ts.html | 196 +++ .../src/services/articleService.ts.html | 220 +++ .../src/services/commentService.ts.html | 346 ++++ .../lcov-report/src/services/index.html | 191 +++ .../src/services/likeService.ts.html | 187 ++ .../src/services/productService.ts.html | 289 ++++ .../src/services/userService.ts.html | 229 +++ .../coverage/lcov-report/src/socket.ts.html | 130 ++ .../lcov-report/src/socket/index.html | 131 ++ .../lcov-report/src/socket/io.ts.html | 145 ++ .../lcov-report/src/socket/socket.ts.html | 154 ++ .../test/helpers/authHelper.ts.html | 154 ++ .../lcov-report/test/helpers/index.html | 131 ++ .../test/helpers/resetDatabase.ts.html | 124 ++ .../coverage/lcov-report/test/index.html | 131 ++ .../coverage/lcov-report/test/setup.ts.html | 118 ++ .../coverage/lcov-report/test/utils.ts.html | 181 ++ .../lcov-report/tests/helpers/auth.ts.html | 211 +++ .../lcov-report/tests/helpers/index.html | 116 ++ mission 9/coverage/lcov.info | 1510 +++++++++++++++++ mission 9/jest.config.ts | 18 +- mission 9/package.json | 3 +- mission 9/src/app.ts | 26 +- mission 9/src/controllers/alertController.ts | 17 +- mission 9/src/controllers/userController.ts | 3 +- mission 9/src/lib/passport/jwtStrategy.ts | 11 +- mission 9/src/repositories/alertRepository.ts | 6 + mission 9/src/routers/alertRouter.ts | 2 - mission 9/src/routers/articleRouter.ts | 7 +- mission 9/src/routers/commentRouter.ts | 9 +- mission 9/src/routers/index.ts | 4 +- mission 9/src/routers/productRouter.ts | 9 +- mission 9/src/services/alertService.ts | 17 +- mission 9/src/services/commentService.ts | 12 +- mission 9/src/services/productService.ts | 2 +- mission 9/src/socket.ts | 16 - mission 9/src/socket/io.ts | 20 + mission 9/src/socket/socket.ts | 23 + mission 9/test/articleService.test.ts | 125 -- mission 9/test/commentService.test.ts | 203 --- mission 9/test/hello.test.ts | 4 - mission 9/test/productService.test.ts | 121 -- mission 9/tests/_mocks_/alertRepository.ts | 7 + mission 9/tests/_mocks_/productRepository.ts | 7 + mission 9/tests/_mocks_/userRepositoy.ts | 7 + mission 9/tests/alertService.test.ts | 60 + mission 9/tests/helpers/auth.ts | 42 + mission 9/tests/product.integration.test.ts | 45 + mission 9/tests/productService.test.ts | 89 + mission 9/tests/userService.test.ts | 65 + 101 files changed, 14607 insertions(+), 514 deletions(-) create mode 100644 mission 9/coverage/clover.xml create mode 100644 mission 9/coverage/coverage-final.json create mode 100644 mission 9/coverage/lcov-report/base.css create mode 100644 mission 9/coverage/lcov-report/block-navigation.js create mode 100644 mission 9/coverage/lcov-report/favicon.png create mode 100644 mission 9/coverage/lcov-report/index.html create mode 100644 mission 9/coverage/lcov-report/prettify.css create mode 100644 mission 9/coverage/lcov-report/prettify.js create mode 100644 mission 9/coverage/lcov-report/sort-arrow-sprite.png create mode 100644 mission 9/coverage/lcov-report/sorter.js create mode 100644 mission 9/coverage/lcov-report/src/app.ts.html create mode 100644 mission 9/coverage/lcov-report/src/controllers/alertController.ts.html create mode 100644 mission 9/coverage/lcov-report/src/controllers/articleController.ts.html create mode 100644 mission 9/coverage/lcov-report/src/controllers/commentController.ts.html create mode 100644 mission 9/coverage/lcov-report/src/controllers/index.html create mode 100644 mission 9/coverage/lcov-report/src/controllers/likeController.ts.html create mode 100644 mission 9/coverage/lcov-report/src/controllers/photoController.ts.html create mode 100644 mission 9/coverage/lcov-report/src/controllers/productController.ts.html create mode 100644 mission 9/coverage/lcov-report/src/controllers/userController.ts.html create mode 100644 mission 9/coverage/lcov-report/src/dtos/article.dto.ts.html create mode 100644 mission 9/coverage/lcov-report/src/dtos/index.html create mode 100644 mission 9/coverage/lcov-report/src/dtos/product.dto.ts.html create mode 100644 mission 9/coverage/lcov-report/src/dtos/user.dto.ts.html create mode 100644 mission 9/coverage/lcov-report/src/index.html create mode 100644 mission 9/coverage/lcov-report/src/lib/constants.ts.html create mode 100644 mission 9/coverage/lcov-report/src/lib/cookieUtil.ts.html create mode 100644 mission 9/coverage/lcov-report/src/lib/index.html create mode 100644 mission 9/coverage/lcov-report/src/lib/passport/index.html create mode 100644 mission 9/coverage/lcov-report/src/lib/passport/index.ts.html create mode 100644 mission 9/coverage/lcov-report/src/lib/passport/jwtStrategy.ts.html create mode 100644 mission 9/coverage/lcov-report/src/lib/passport/localStrategy.ts.html create mode 100644 mission 9/coverage/lcov-report/src/lib/prisma.ts.html create mode 100644 mission 9/coverage/lcov-report/src/lib/token.ts.html create mode 100644 mission 9/coverage/lcov-report/src/middlewares/errorHandler.ts.html create mode 100644 mission 9/coverage/lcov-report/src/middlewares/index.html create mode 100644 mission 9/coverage/lcov-report/src/repositories/alertRepository.ts.html create mode 100644 mission 9/coverage/lcov-report/src/repositories/articleRepository.ts.html create mode 100644 mission 9/coverage/lcov-report/src/repositories/commentRepository.ts.html create mode 100644 mission 9/coverage/lcov-report/src/repositories/index.html create mode 100644 mission 9/coverage/lcov-report/src/repositories/likeRepository.ts.html create mode 100644 mission 9/coverage/lcov-report/src/repositories/productRepository.ts.html create mode 100644 mission 9/coverage/lcov-report/src/repositories/userRepository.ts.html create mode 100644 mission 9/coverage/lcov-report/src/routers/alertRouter.ts.html create mode 100644 mission 9/coverage/lcov-report/src/routers/articleRouter.ts.html create mode 100644 mission 9/coverage/lcov-report/src/routers/commentRouter.ts.html create mode 100644 mission 9/coverage/lcov-report/src/routers/index.html create mode 100644 mission 9/coverage/lcov-report/src/routers/index.ts.html create mode 100644 mission 9/coverage/lcov-report/src/routers/likeRouter.ts.html create mode 100644 mission 9/coverage/lcov-report/src/routers/photoRouter.ts.html create mode 100644 mission 9/coverage/lcov-report/src/routers/productRouter.ts.html create mode 100644 mission 9/coverage/lcov-report/src/routers/userRouter.ts.html create mode 100644 mission 9/coverage/lcov-report/src/services/alertService.ts.html create mode 100644 mission 9/coverage/lcov-report/src/services/articleService.ts.html create mode 100644 mission 9/coverage/lcov-report/src/services/commentService.ts.html create mode 100644 mission 9/coverage/lcov-report/src/services/index.html create mode 100644 mission 9/coverage/lcov-report/src/services/likeService.ts.html create mode 100644 mission 9/coverage/lcov-report/src/services/productService.ts.html create mode 100644 mission 9/coverage/lcov-report/src/services/userService.ts.html create mode 100644 mission 9/coverage/lcov-report/src/socket.ts.html create mode 100644 mission 9/coverage/lcov-report/src/socket/index.html create mode 100644 mission 9/coverage/lcov-report/src/socket/io.ts.html create mode 100644 mission 9/coverage/lcov-report/src/socket/socket.ts.html create mode 100644 mission 9/coverage/lcov-report/test/helpers/authHelper.ts.html create mode 100644 mission 9/coverage/lcov-report/test/helpers/index.html create mode 100644 mission 9/coverage/lcov-report/test/helpers/resetDatabase.ts.html create mode 100644 mission 9/coverage/lcov-report/test/index.html create mode 100644 mission 9/coverage/lcov-report/test/setup.ts.html create mode 100644 mission 9/coverage/lcov-report/test/utils.ts.html create mode 100644 mission 9/coverage/lcov-report/tests/helpers/auth.ts.html create mode 100644 mission 9/coverage/lcov-report/tests/helpers/index.html create mode 100644 mission 9/coverage/lcov.info delete mode 100644 mission 9/src/socket.ts create mode 100644 mission 9/src/socket/io.ts create mode 100644 mission 9/src/socket/socket.ts delete mode 100644 mission 9/test/articleService.test.ts delete mode 100644 mission 9/test/commentService.test.ts delete mode 100644 mission 9/test/hello.test.ts delete mode 100644 mission 9/test/productService.test.ts create mode 100644 mission 9/tests/_mocks_/alertRepository.ts create mode 100644 mission 9/tests/_mocks_/productRepository.ts create mode 100644 mission 9/tests/_mocks_/userRepositoy.ts create mode 100644 mission 9/tests/alertService.test.ts create mode 100644 mission 9/tests/helpers/auth.ts create mode 100644 mission 9/tests/product.integration.test.ts create mode 100644 mission 9/tests/productService.test.ts create mode 100644 mission 9/tests/userService.test.ts diff --git a/mission 9/coverage/clover.xml b/mission 9/coverage/clover.xml new file mode 100644 index 000000000..495a99c49 --- /dev/null +++ b/mission 9/coverage/clover.xml @@ -0,0 +1,815 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mission 9/coverage/coverage-final.json b/mission 9/coverage/coverage-final.json new file mode 100644 index 000000000..c952765f1 --- /dev/null +++ b/mission 9/coverage/coverage-final.json @@ -0,0 +1,42 @@ +{"/home/baturs/4-sprint-mission/mission 9/src/app.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/app.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":30}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":41}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":37}},"3":{"start":{"line":4,"column":0},"end":{"line":4,"column":39}},"4":{"start":{"line":5,"column":0},"end":{"line":5,"column":44}},"5":{"start":{"line":6,"column":0},"end":{"line":6,"column":24}},"6":{"start":{"line":7,"column":0},"end":{"line":7,"column":58}},"7":{"start":{"line":8,"column":0},"end":{"line":8,"column":24}},"8":{"start":{"line":9,"column":0},"end":{"line":9,"column":37}},"9":{"start":{"line":10,"column":0},"end":{"line":10,"column":49}},"10":{"start":{"line":12,"column":12},"end":{"line":12,"column":21}},"11":{"start":{"line":40,"column":9},"end":{"line":40,"column":12}},"12":{"start":{"line":14,"column":0},"end":{"line":14,"column":48}},"13":{"start":{"line":15,"column":0},"end":{"line":15,"column":24}},"14":{"start":{"line":16,"column":0},"end":{"line":16,"column":24}},"15":{"start":{"line":18,"column":20},"end":{"line":22,"column":2}},"16":{"start":{"line":23,"column":0},"end":{"line":23,"column":27}},"17":{"start":{"line":25,"column":0},"end":{"line":25,"column":31}},"18":{"start":{"line":26,"column":0},"end":{"line":26,"column":16}},"19":{"start":{"line":28,"column":0},"end":{"line":28,"column":48}},"20":{"start":{"line":29,"column":0},"end":{"line":29,"column":22}},"21":{"start":{"line":31,"column":15},"end":{"line":31,"column":37}},"22":{"start":{"line":33,"column":0},"end":{"line":33,"column":15}},"23":{"start":{"line":34,"column":0},"end":{"line":34,"column":17}},"24":{"start":{"line":36,"column":0},"end":{"line":38,"column":3}},"25":{"start":{"line":37,"column":2},"end":{"line":37,"column":63}},"26":{"start":{"line":41,"column":0},"end":{"line":41,"column":19}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":36,"column":20},"end":{"line":36,"column":23}},"loc":{"start":{"line":36,"column":25},"end":{"line":38,"column":1}}}},"branchMap":{},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":1,"26":1},"f":{"0":1},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/controllers/alertController.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/controllers/alertController.ts","statementMap":{"0":{"start":{"line":2,"column":0},"end":{"line":2,"column":56}},"1":{"start":{"line":3,"column":0},"end":{"line":3,"column":33}},"2":{"start":{"line":6,"column":10},"end":{"line":6,"column":39}},"3":{"start":{"line":8,"column":2},"end":{"line":14,"column":4}},"4":{"start":{"line":9,"column":4},"end":{"line":10,"column":79}},"5":{"start":{"line":10,"column":6},"end":{"line":10,"column":79}},"6":{"start":{"line":11,"column":19},"end":{"line":11,"column":30}},"7":{"start":{"line":12,"column":19},"end":{"line":12,"column":50}},"8":{"start":{"line":13,"column":4},"end":{"line":13,"column":21}},"9":{"start":{"line":16,"column":2},"end":{"line":35,"column":4}},"10":{"start":{"line":17,"column":4},"end":{"line":18,"column":79}},"11":{"start":{"line":18,"column":6},"end":{"line":18,"column":79}},"12":{"start":{"line":20,"column":19},"end":{"line":20,"column":30}},"13":{"start":{"line":21,"column":20},"end":{"line":21,"column":41}},"14":{"start":{"line":23,"column":4},"end":{"line":25,"column":5}},"15":{"start":{"line":24,"column":6},"end":{"line":24,"column":43}},"16":{"start":{"line":27,"column":20},"end":{"line":27,"column":60}},"17":{"start":{"line":29,"column":4},"end":{"line":33,"column":5}},"18":{"start":{"line":30,"column":6},"end":{"line":32,"column":9}},"19":{"start":{"line":34,"column":4},"end":{"line":34,"column":27}},"20":{"start":{"line":5,"column":0},"end":{"line":5,"column":13}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":5,"column":0},"end":{"line":5,"column":13}},"loc":{"start":{"line":5,"column":0},"end":{"line":36,"column":1}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":8,"column":9},"end":{"line":8,"column":14}},"loc":{"start":{"line":8,"column":47},"end":{"line":14,"column":3}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":16,"column":15},"end":{"line":16,"column":20}},"loc":{"start":{"line":16,"column":53},"end":{"line":35,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":9,"column":4},"end":{"line":10,"column":79}},"type":"if","locations":[{"start":{"line":9,"column":4},"end":{"line":10,"column":79}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":17,"column":4},"end":{"line":18,"column":79}},"type":"if","locations":[{"start":{"line":17,"column":4},"end":{"line":18,"column":79}},{"start":{},"end":{}}]},"2":{"loc":{"start":{"line":23,"column":4},"end":{"line":25,"column":5}},"type":"if","locations":[{"start":{"line":23,"column":4},"end":{"line":25,"column":5}},{"start":{},"end":{}}]},"3":{"loc":{"start":{"line":29,"column":4},"end":{"line":33,"column":5}},"type":"if","locations":[{"start":{"line":29,"column":4},"end":{"line":33,"column":5}},{"start":{},"end":{}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":0,"5":0,"6":0,"7":0,"8":0,"9":1,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":1},"f":{"0":1,"1":0,"2":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/controllers/articleController.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/controllers/articleController.ts","statementMap":{"0":{"start":{"line":2,"column":0},"end":{"line":2,"column":33}},"1":{"start":{"line":3,"column":0},"end":{"line":3,"column":60}},"2":{"start":{"line":4,"column":0},"end":{"line":4,"column":99}},"3":{"start":{"line":6,"column":23},"end":{"line":6,"column":43}},"4":{"start":{"line":10,"column":4},"end":{"line":18,"column":5}},"5":{"start":{"line":11,"column":6},"end":{"line":11,"column":94}},"6":{"start":{"line":11,"column":21},"end":{"line":11,"column":94}},"7":{"start":{"line":13,"column":21},"end":{"line":13,"column":56}},"8":{"start":{"line":14,"column":22},"end":{"line":14,"column":70}},"9":{"start":{"line":15,"column":6},"end":{"line":15,"column":47}},"10":{"start":{"line":17,"column":6},"end":{"line":17,"column":16}},"11":{"start":{"line":22,"column":4},"end":{"line":28,"column":5}},"12":{"start":{"line":23,"column":21},"end":{"line":23,"column":56}},"13":{"start":{"line":24,"column":23},"end":{"line":24,"column":56}},"14":{"start":{"line":25,"column":6},"end":{"line":25,"column":43}},"15":{"start":{"line":27,"column":6},"end":{"line":27,"column":16}},"16":{"start":{"line":32,"column":4},"end":{"line":39,"column":5}},"17":{"start":{"line":33,"column":24},"end":{"line":33,"column":45}},"18":{"start":{"line":34,"column":22},"end":{"line":34,"column":63}},"19":{"start":{"line":35,"column":6},"end":{"line":35,"column":95}},"20":{"start":{"line":35,"column":20},"end":{"line":35,"column":95}},"21":{"start":{"line":36,"column":6},"end":{"line":36,"column":42}},"22":{"start":{"line":38,"column":6},"end":{"line":38,"column":16}},"23":{"start":{"line":43,"column":4},"end":{"line":54,"column":5}},"24":{"start":{"line":44,"column":6},"end":{"line":44,"column":94}},"25":{"start":{"line":44,"column":21},"end":{"line":44,"column":94}},"26":{"start":{"line":45,"column":21},"end":{"line":45,"column":97}},"27":{"start":{"line":46,"column":24},"end":{"line":46,"column":45}},"28":{"start":{"line":47,"column":22},"end":{"line":47,"column":81}},"29":{"start":{"line":49,"column":6},"end":{"line":49,"column":42}},"30":{"start":{"line":51,"column":6},"end":{"line":51,"column":114}},"31":{"start":{"line":51,"column":39},"end":{"line":51,"column":114}},"32":{"start":{"line":52,"column":6},"end":{"line":52,"column":113}},"33":{"start":{"line":52,"column":39},"end":{"line":52,"column":113}},"34":{"start":{"line":53,"column":6},"end":{"line":53,"column":16}},"35":{"start":{"line":58,"column":4},"end":{"line":68,"column":5}},"36":{"start":{"line":59,"column":6},"end":{"line":59,"column":94}},"37":{"start":{"line":59,"column":21},"end":{"line":59,"column":94}},"38":{"start":{"line":61,"column":24},"end":{"line":61,"column":45}},"39":{"start":{"line":62,"column":6},"end":{"line":62,"column":58}},"40":{"start":{"line":63,"column":6},"end":{"line":63,"column":42}},"41":{"start":{"line":65,"column":6},"end":{"line":65,"column":114}},"42":{"start":{"line":65,"column":39},"end":{"line":65,"column":114}},"43":{"start":{"line":66,"column":6},"end":{"line":66,"column":113}},"44":{"start":{"line":66,"column":39},"end":{"line":66,"column":113}},"45":{"start":{"line":67,"column":6},"end":{"line":67,"column":16}},"46":{"start":{"line":8,"column":0},"end":{"line":8,"column":13}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":9,"column":2},"end":{"line":9,"column":7}},"loc":{"start":{"line":9,"column":62},"end":{"line":19,"column":3}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":21,"column":2},"end":{"line":21,"column":7}},"loc":{"start":{"line":21,"column":60},"end":{"line":29,"column":3}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":31,"column":2},"end":{"line":31,"column":7}},"loc":{"start":{"line":31,"column":62},"end":{"line":40,"column":3}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":42,"column":2},"end":{"line":42,"column":7}},"loc":{"start":{"line":42,"column":62},"end":{"line":55,"column":3}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":57,"column":2},"end":{"line":57,"column":7}},"loc":{"start":{"line":57,"column":62},"end":{"line":69,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":11,"column":6},"end":{"line":11,"column":94}},"type":"if","locations":[{"start":{"line":11,"column":6},"end":{"line":11,"column":94}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":35,"column":6},"end":{"line":35,"column":95}},"type":"if","locations":[{"start":{"line":35,"column":6},"end":{"line":35,"column":95}},{"start":{},"end":{}}]},"2":{"loc":{"start":{"line":44,"column":6},"end":{"line":44,"column":94}},"type":"if","locations":[{"start":{"line":44,"column":6},"end":{"line":44,"column":94}},{"start":{},"end":{}}]},"3":{"loc":{"start":{"line":51,"column":6},"end":{"line":51,"column":114}},"type":"if","locations":[{"start":{"line":51,"column":6},"end":{"line":51,"column":114}},{"start":{},"end":{}}]},"4":{"loc":{"start":{"line":52,"column":6},"end":{"line":52,"column":113}},"type":"if","locations":[{"start":{"line":52,"column":6},"end":{"line":52,"column":113}},{"start":{},"end":{}}]},"5":{"loc":{"start":{"line":59,"column":6},"end":{"line":59,"column":94}},"type":"if","locations":[{"start":{"line":59,"column":6},"end":{"line":59,"column":94}},{"start":{},"end":{}}]},"6":{"loc":{"start":{"line":65,"column":6},"end":{"line":65,"column":114}},"type":"if","locations":[{"start":{"line":65,"column":6},"end":{"line":65,"column":114}},{"start":{},"end":{}}]},"7":{"loc":{"start":{"line":66,"column":6},"end":{"line":66,"column":113}},"type":"if","locations":[{"start":{"line":66,"column":6},"end":{"line":66,"column":113}},{"start":{},"end":{}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":1},"f":{"0":0,"1":0,"2":0,"3":0,"4":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/controllers/commentController.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/controllers/commentController.ts","statementMap":{"0":{"start":{"line":2,"column":0},"end":{"line":2,"column":24}},"1":{"start":{"line":3,"column":0},"end":{"line":3,"column":33}},"2":{"start":{"line":4,"column":0},"end":{"line":4,"column":60}},"3":{"start":{"line":6,"column":23},"end":{"line":6,"column":43}},"4":{"start":{"line":8,"column":22},"end":{"line":10,"column":2}},"5":{"start":{"line":12,"column":26},"end":{"line":15,"column":2}},"6":{"start":{"line":19,"column":4},"end":{"line":27,"column":5}},"7":{"start":{"line":20,"column":6},"end":{"line":20,"column":94}},"8":{"start":{"line":20,"column":21},"end":{"line":20,"column":94}},"9":{"start":{"line":21,"column":24},"end":{"line":21,"column":45}},"10":{"start":{"line":22,"column":21},"end":{"line":22,"column":50}},"11":{"start":{"line":23,"column":22},"end":{"line":23,"column":103}},"12":{"start":{"line":24,"column":6},"end":{"line":24,"column":47}},"13":{"start":{"line":26,"column":6},"end":{"line":26,"column":16}},"14":{"start":{"line":31,"column":4},"end":{"line":39,"column":5}},"15":{"start":{"line":32,"column":6},"end":{"line":32,"column":94}},"16":{"start":{"line":32,"column":21},"end":{"line":32,"column":94}},"17":{"start":{"line":33,"column":24},"end":{"line":33,"column":45}},"18":{"start":{"line":34,"column":21},"end":{"line":34,"column":50}},"19":{"start":{"line":35,"column":22},"end":{"line":35,"column":103}},"20":{"start":{"line":36,"column":6},"end":{"line":36,"column":47}},"21":{"start":{"line":38,"column":6},"end":{"line":38,"column":16}},"22":{"start":{"line":43,"column":4},"end":{"line":53,"column":5}},"23":{"start":{"line":44,"column":6},"end":{"line":44,"column":94}},"24":{"start":{"line":44,"column":21},"end":{"line":44,"column":94}},"25":{"start":{"line":45,"column":24},"end":{"line":45,"column":45}},"26":{"start":{"line":46,"column":21},"end":{"line":46,"column":50}},"27":{"start":{"line":47,"column":22},"end":{"line":47,"column":96}},"28":{"start":{"line":48,"column":6},"end":{"line":48,"column":42}},"29":{"start":{"line":50,"column":6},"end":{"line":50,"column":114}},"30":{"start":{"line":50,"column":39},"end":{"line":50,"column":114}},"31":{"start":{"line":51,"column":6},"end":{"line":51,"column":113}},"32":{"start":{"line":51,"column":39},"end":{"line":51,"column":113}},"33":{"start":{"line":52,"column":6},"end":{"line":52,"column":16}},"34":{"start":{"line":57,"column":4},"end":{"line":66,"column":5}},"35":{"start":{"line":58,"column":6},"end":{"line":58,"column":94}},"36":{"start":{"line":58,"column":21},"end":{"line":58,"column":94}},"37":{"start":{"line":59,"column":24},"end":{"line":59,"column":45}},"38":{"start":{"line":60,"column":6},"end":{"line":60,"column":65}},"39":{"start":{"line":61,"column":6},"end":{"line":61,"column":42}},"40":{"start":{"line":63,"column":6},"end":{"line":63,"column":114}},"41":{"start":{"line":63,"column":39},"end":{"line":63,"column":114}},"42":{"start":{"line":64,"column":6},"end":{"line":64,"column":113}},"43":{"start":{"line":64,"column":39},"end":{"line":64,"column":113}},"44":{"start":{"line":65,"column":6},"end":{"line":65,"column":16}},"45":{"start":{"line":70,"column":4},"end":{"line":76,"column":5}},"46":{"start":{"line":71,"column":21},"end":{"line":71,"column":93}},"47":{"start":{"line":72,"column":23},"end":{"line":72,"column":88}},"48":{"start":{"line":73,"column":6},"end":{"line":73,"column":43}},"49":{"start":{"line":75,"column":6},"end":{"line":75,"column":16}},"50":{"start":{"line":80,"column":4},"end":{"line":86,"column":5}},"51":{"start":{"line":81,"column":21},"end":{"line":81,"column":93}},"52":{"start":{"line":82,"column":23},"end":{"line":82,"column":88}},"53":{"start":{"line":83,"column":6},"end":{"line":83,"column":43}},"54":{"start":{"line":85,"column":6},"end":{"line":85,"column":16}},"55":{"start":{"line":17,"column":0},"end":{"line":17,"column":13}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":18,"column":2},"end":{"line":18,"column":7}},"loc":{"start":{"line":18,"column":76},"end":{"line":28,"column":3}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":30,"column":2},"end":{"line":30,"column":7}},"loc":{"start":{"line":30,"column":76},"end":{"line":40,"column":3}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":42,"column":2},"end":{"line":42,"column":7}},"loc":{"start":{"line":42,"column":69},"end":{"line":54,"column":3}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":56,"column":2},"end":{"line":56,"column":7}},"loc":{"start":{"line":56,"column":69},"end":{"line":67,"column":3}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":69,"column":2},"end":{"line":69,"column":7}},"loc":{"start":{"line":69,"column":74},"end":{"line":77,"column":3}}},"5":{"name":"(anonymous_6)","decl":{"start":{"line":79,"column":2},"end":{"line":79,"column":7}},"loc":{"start":{"line":79,"column":74},"end":{"line":87,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":20,"column":6},"end":{"line":20,"column":94}},"type":"if","locations":[{"start":{"line":20,"column":6},"end":{"line":20,"column":94}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":32,"column":6},"end":{"line":32,"column":94}},"type":"if","locations":[{"start":{"line":32,"column":6},"end":{"line":32,"column":94}},{"start":{},"end":{}}]},"2":{"loc":{"start":{"line":44,"column":6},"end":{"line":44,"column":94}},"type":"if","locations":[{"start":{"line":44,"column":6},"end":{"line":44,"column":94}},{"start":{},"end":{}}]},"3":{"loc":{"start":{"line":50,"column":6},"end":{"line":50,"column":114}},"type":"if","locations":[{"start":{"line":50,"column":6},"end":{"line":50,"column":114}},{"start":{},"end":{}}]},"4":{"loc":{"start":{"line":51,"column":6},"end":{"line":51,"column":113}},"type":"if","locations":[{"start":{"line":51,"column":6},"end":{"line":51,"column":113}},{"start":{},"end":{}}]},"5":{"loc":{"start":{"line":58,"column":6},"end":{"line":58,"column":94}},"type":"if","locations":[{"start":{"line":58,"column":6},"end":{"line":58,"column":94}},{"start":{},"end":{}}]},"6":{"loc":{"start":{"line":63,"column":6},"end":{"line":63,"column":114}},"type":"if","locations":[{"start":{"line":63,"column":6},"end":{"line":63,"column":114}},{"start":{},"end":{}}]},"7":{"loc":{"start":{"line":64,"column":6},"end":{"line":64,"column":113}},"type":"if","locations":[{"start":{"line":64,"column":6},"end":{"line":64,"column":113}},{"start":{},"end":{}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":1},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/controllers/likeController.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/controllers/likeController.ts","statementMap":{"0":{"start":{"line":2,"column":0},"end":{"line":2,"column":33}},"1":{"start":{"line":3,"column":0},"end":{"line":3,"column":54}},"2":{"start":{"line":5,"column":20},"end":{"line":5,"column":37}},"3":{"start":{"line":9,"column":4},"end":{"line":9,"column":92}},"4":{"start":{"line":9,"column":19},"end":{"line":9,"column":92}},"5":{"start":{"line":10,"column":4},"end":{"line":16,"column":5}},"6":{"start":{"line":11,"column":21},"end":{"line":11,"column":86}},"7":{"start":{"line":12,"column":6},"end":{"line":12,"column":84}},"8":{"start":{"line":14,"column":6},"end":{"line":14,"column":122}},"9":{"start":{"line":14,"column":47},"end":{"line":14,"column":122}},"10":{"start":{"line":15,"column":6},"end":{"line":15,"column":16}},"11":{"start":{"line":20,"column":4},"end":{"line":20,"column":92}},"12":{"start":{"line":20,"column":19},"end":{"line":20,"column":92}},"13":{"start":{"line":21,"column":4},"end":{"line":27,"column":5}},"14":{"start":{"line":22,"column":21},"end":{"line":22,"column":86}},"15":{"start":{"line":23,"column":6},"end":{"line":23,"column":84}},"16":{"start":{"line":25,"column":6},"end":{"line":25,"column":122}},"17":{"start":{"line":25,"column":47},"end":{"line":25,"column":122}},"18":{"start":{"line":26,"column":6},"end":{"line":26,"column":16}},"19":{"start":{"line":31,"column":4},"end":{"line":31,"column":92}},"20":{"start":{"line":31,"column":19},"end":{"line":31,"column":92}},"21":{"start":{"line":32,"column":4},"end":{"line":38,"column":5}},"22":{"start":{"line":33,"column":28},"end":{"line":33,"column":75}},"23":{"start":{"line":34,"column":23},"end":{"line":34,"column":82}},"24":{"start":{"line":34,"column":49},"end":{"line":34,"column":80}},"25":{"start":{"line":35,"column":6},"end":{"line":35,"column":43}},"26":{"start":{"line":37,"column":6},"end":{"line":37,"column":16}},"27":{"start":{"line":42,"column":4},"end":{"line":42,"column":92}},"28":{"start":{"line":42,"column":19},"end":{"line":42,"column":92}},"29":{"start":{"line":43,"column":4},"end":{"line":49,"column":5}},"30":{"start":{"line":44,"column":28},"end":{"line":44,"column":75}},"31":{"start":{"line":45,"column":23},"end":{"line":45,"column":82}},"32":{"start":{"line":45,"column":49},"end":{"line":45,"column":80}},"33":{"start":{"line":46,"column":6},"end":{"line":46,"column":43}},"34":{"start":{"line":48,"column":6},"end":{"line":48,"column":16}},"35":{"start":{"line":7,"column":0},"end":{"line":7,"column":13}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":8,"column":2},"end":{"line":8,"column":7}},"loc":{"start":{"line":8,"column":67},"end":{"line":17,"column":3}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":19,"column":2},"end":{"line":19,"column":7}},"loc":{"start":{"line":19,"column":67},"end":{"line":28,"column":3}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":30,"column":2},"end":{"line":30,"column":7}},"loc":{"start":{"line":30,"column":72},"end":{"line":39,"column":3}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":34,"column":41},"end":{"line":34,"column":42}},"loc":{"start":{"line":34,"column":49},"end":{"line":34,"column":80}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":41,"column":2},"end":{"line":41,"column":7}},"loc":{"start":{"line":41,"column":72},"end":{"line":50,"column":3}}},"5":{"name":"(anonymous_6)","decl":{"start":{"line":45,"column":41},"end":{"line":45,"column":42}},"loc":{"start":{"line":45,"column":49},"end":{"line":45,"column":80}}}},"branchMap":{"0":{"loc":{"start":{"line":9,"column":4},"end":{"line":9,"column":92}},"type":"if","locations":[{"start":{"line":9,"column":4},"end":{"line":9,"column":92}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":14,"column":6},"end":{"line":14,"column":122}},"type":"if","locations":[{"start":{"line":14,"column":6},"end":{"line":14,"column":122}},{"start":{},"end":{}}]},"2":{"loc":{"start":{"line":20,"column":4},"end":{"line":20,"column":92}},"type":"if","locations":[{"start":{"line":20,"column":4},"end":{"line":20,"column":92}},{"start":{},"end":{}}]},"3":{"loc":{"start":{"line":25,"column":6},"end":{"line":25,"column":122}},"type":"if","locations":[{"start":{"line":25,"column":6},"end":{"line":25,"column":122}},{"start":{},"end":{}}]},"4":{"loc":{"start":{"line":31,"column":4},"end":{"line":31,"column":92}},"type":"if","locations":[{"start":{"line":31,"column":4},"end":{"line":31,"column":92}},{"start":{},"end":{}}]},"5":{"loc":{"start":{"line":42,"column":4},"end":{"line":42,"column":92}},"type":"if","locations":[{"start":{"line":42,"column":4},"end":{"line":42,"column":92}},{"start":{},"end":{}}]}},"s":{"0":1,"1":1,"2":1,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":1},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/controllers/photoController.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/controllers/photoController.ts","statementMap":{"0":{"start":{"line":2,"column":0},"end":{"line":2,"column":35}},"1":{"start":{"line":3,"column":0},"end":{"line":3,"column":33}},"2":{"start":{"line":7,"column":4},"end":{"line":7,"column":76}},"3":{"start":{"line":7,"column":19},"end":{"line":7,"column":76}},"4":{"start":{"line":9,"column":4},"end":{"line":11,"column":5}},"5":{"start":{"line":10,"column":6},"end":{"line":10,"column":82}},"6":{"start":{"line":13,"column":4},"end":{"line":27,"column":5}},"7":{"start":{"line":14,"column":23},"end":{"line":14,"column":55}},"8":{"start":{"line":16,"column":26},"end":{"line":19,"column":8}},"9":{"start":{"line":21,"column":6},"end":{"line":24,"column":9}},"10":{"start":{"line":26,"column":6},"end":{"line":26,"column":16}},"11":{"start":{"line":5,"column":0},"end":{"line":5,"column":13}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":6,"column":2},"end":{"line":6,"column":7}},"loc":{"start":{"line":6,"column":62},"end":{"line":28,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":7,"column":4},"end":{"line":7,"column":76}},"type":"if","locations":[{"start":{"line":7,"column":4},"end":{"line":7,"column":76}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":9,"column":4},"end":{"line":11,"column":5}},"type":"if","locations":[{"start":{"line":9,"column":4},"end":{"line":11,"column":5}},{"start":{},"end":{}}]}},"s":{"0":1,"1":1,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":1},"f":{"0":0},"b":{"0":[0,0],"1":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/controllers/productController.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/controllers/productController.ts","statementMap":{"0":{"start":{"line":2,"column":0},"end":{"line":2,"column":33}},"1":{"start":{"line":3,"column":0},"end":{"line":3,"column":60}},"2":{"start":{"line":4,"column":0},"end":{"line":4,"column":99}},"3":{"start":{"line":6,"column":23},"end":{"line":6,"column":43}},"4":{"start":{"line":10,"column":4},"end":{"line":17,"column":5}},"5":{"start":{"line":11,"column":6},"end":{"line":11,"column":94}},"6":{"start":{"line":11,"column":21},"end":{"line":11,"column":94}},"7":{"start":{"line":12,"column":21},"end":{"line":12,"column":56}},"8":{"start":{"line":13,"column":22},"end":{"line":13,"column":70}},"9":{"start":{"line":14,"column":6},"end":{"line":14,"column":47}},"10":{"start":{"line":16,"column":6},"end":{"line":16,"column":16}},"11":{"start":{"line":21,"column":4},"end":{"line":27,"column":5}},"12":{"start":{"line":22,"column":21},"end":{"line":22,"column":56}},"13":{"start":{"line":23,"column":23},"end":{"line":23,"column":56}},"14":{"start":{"line":24,"column":6},"end":{"line":24,"column":43}},"15":{"start":{"line":26,"column":6},"end":{"line":26,"column":16}},"16":{"start":{"line":31,"column":4},"end":{"line":38,"column":5}},"17":{"start":{"line":32,"column":24},"end":{"line":32,"column":45}},"18":{"start":{"line":33,"column":22},"end":{"line":33,"column":63}},"19":{"start":{"line":34,"column":6},"end":{"line":34,"column":95}},"20":{"start":{"line":34,"column":20},"end":{"line":34,"column":95}},"21":{"start":{"line":35,"column":6},"end":{"line":35,"column":42}},"22":{"start":{"line":37,"column":6},"end":{"line":37,"column":16}},"23":{"start":{"line":42,"column":4},"end":{"line":53,"column":5}},"24":{"start":{"line":43,"column":6},"end":{"line":43,"column":94}},"25":{"start":{"line":43,"column":21},"end":{"line":43,"column":94}},"26":{"start":{"line":44,"column":21},"end":{"line":44,"column":131}},"27":{"start":{"line":45,"column":24},"end":{"line":45,"column":45}},"28":{"start":{"line":46,"column":22},"end":{"line":46,"column":81}},"29":{"start":{"line":48,"column":6},"end":{"line":48,"column":42}},"30":{"start":{"line":50,"column":6},"end":{"line":50,"column":114}},"31":{"start":{"line":50,"column":39},"end":{"line":50,"column":114}},"32":{"start":{"line":51,"column":6},"end":{"line":51,"column":113}},"33":{"start":{"line":51,"column":39},"end":{"line":51,"column":113}},"34":{"start":{"line":52,"column":6},"end":{"line":52,"column":16}},"35":{"start":{"line":57,"column":4},"end":{"line":66,"column":5}},"36":{"start":{"line":58,"column":6},"end":{"line":58,"column":94}},"37":{"start":{"line":58,"column":21},"end":{"line":58,"column":94}},"38":{"start":{"line":59,"column":24},"end":{"line":59,"column":45}},"39":{"start":{"line":60,"column":6},"end":{"line":60,"column":58}},"40":{"start":{"line":61,"column":6},"end":{"line":61,"column":42}},"41":{"start":{"line":63,"column":6},"end":{"line":63,"column":114}},"42":{"start":{"line":63,"column":39},"end":{"line":63,"column":114}},"43":{"start":{"line":64,"column":6},"end":{"line":64,"column":113}},"44":{"start":{"line":64,"column":39},"end":{"line":64,"column":113}},"45":{"start":{"line":65,"column":6},"end":{"line":65,"column":16}},"46":{"start":{"line":8,"column":0},"end":{"line":8,"column":13}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":9,"column":2},"end":{"line":9,"column":7}},"loc":{"start":{"line":9,"column":62},"end":{"line":18,"column":3}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":20,"column":2},"end":{"line":20,"column":7}},"loc":{"start":{"line":20,"column":60},"end":{"line":28,"column":3}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":30,"column":2},"end":{"line":30,"column":7}},"loc":{"start":{"line":30,"column":62},"end":{"line":39,"column":3}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":41,"column":2},"end":{"line":41,"column":7}},"loc":{"start":{"line":41,"column":62},"end":{"line":54,"column":3}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":56,"column":2},"end":{"line":56,"column":7}},"loc":{"start":{"line":56,"column":62},"end":{"line":67,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":11,"column":6},"end":{"line":11,"column":94}},"type":"if","locations":[{"start":{"line":11,"column":6},"end":{"line":11,"column":94}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":34,"column":6},"end":{"line":34,"column":95}},"type":"if","locations":[{"start":{"line":34,"column":6},"end":{"line":34,"column":95}},{"start":{},"end":{}}]},"2":{"loc":{"start":{"line":43,"column":6},"end":{"line":43,"column":94}},"type":"if","locations":[{"start":{"line":43,"column":6},"end":{"line":43,"column":94}},{"start":{},"end":{}}]},"3":{"loc":{"start":{"line":50,"column":6},"end":{"line":50,"column":114}},"type":"if","locations":[{"start":{"line":50,"column":6},"end":{"line":50,"column":114}},{"start":{},"end":{}}]},"4":{"loc":{"start":{"line":51,"column":6},"end":{"line":51,"column":113}},"type":"if","locations":[{"start":{"line":51,"column":6},"end":{"line":51,"column":113}},{"start":{},"end":{}}]},"5":{"loc":{"start":{"line":58,"column":6},"end":{"line":58,"column":94}},"type":"if","locations":[{"start":{"line":58,"column":6},"end":{"line":58,"column":94}},{"start":{},"end":{}}]},"6":{"loc":{"start":{"line":63,"column":6},"end":{"line":63,"column":114}},"type":"if","locations":[{"start":{"line":63,"column":6},"end":{"line":63,"column":114}},{"start":{},"end":{}}]},"7":{"loc":{"start":{"line":64,"column":6},"end":{"line":64,"column":113}},"type":"if","locations":[{"start":{"line":64,"column":6},"end":{"line":64,"column":113}},{"start":{},"end":{}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":1,"12":1,"13":1,"14":1,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":1},"f":{"0":0,"1":1,"2":0,"3":0,"4":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/controllers/userController.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/controllers/userController.ts","statementMap":{"0":{"start":{"line":2,"column":0},"end":{"line":2,"column":33}},"1":{"start":{"line":3,"column":0},"end":{"line":3,"column":54}},"2":{"start":{"line":4,"column":0},"end":{"line":4,"column":71}},"3":{"start":{"line":5,"column":0},"end":{"line":5,"column":109}},"4":{"start":{"line":7,"column":20},"end":{"line":7,"column":37}},"5":{"start":{"line":11,"column":4},"end":{"line":20,"column":5}},"6":{"start":{"line":12,"column":21},"end":{"line":12,"column":55}},"7":{"start":{"line":13,"column":21},"end":{"line":13,"column":55}},"8":{"start":{"line":14,"column":6},"end":{"line":14,"column":46}},"9":{"start":{"line":16,"column":6},"end":{"line":18,"column":7}},"10":{"start":{"line":17,"column":8},"end":{"line":17,"column":87}},"11":{"start":{"line":19,"column":6},"end":{"line":19,"column":16}},"12":{"start":{"line":24,"column":4},"end":{"line":24,"column":92}},"13":{"start":{"line":24,"column":19},"end":{"line":24,"column":92}},"14":{"start":{"line":26,"column":4},"end":{"line":32,"column":5}},"15":{"start":{"line":27,"column":44},"end":{"line":27,"column":87}},"16":{"start":{"line":28,"column":6},"end":{"line":28,"column":54}},"17":{"start":{"line":29,"column":6},"end":{"line":29,"column":71}},"18":{"start":{"line":31,"column":6},"end":{"line":31,"column":16}},"19":{"start":{"line":36,"column":4},"end":{"line":42,"column":5}},"20":{"start":{"line":37,"column":6},"end":{"line":37,"column":94}},"21":{"start":{"line":37,"column":21},"end":{"line":37,"column":94}},"22":{"start":{"line":38,"column":22},"end":{"line":38,"column":63}},"23":{"start":{"line":39,"column":6},"end":{"line":39,"column":42}},"24":{"start":{"line":41,"column":6},"end":{"line":41,"column":16}},"25":{"start":{"line":46,"column":4},"end":{"line":56,"column":5}},"26":{"start":{"line":47,"column":6},"end":{"line":47,"column":94}},"27":{"start":{"line":47,"column":21},"end":{"line":47,"column":94}},"28":{"start":{"line":49,"column":21},"end":{"line":49,"column":53}},"29":{"start":{"line":50,"column":26},"end":{"line":50,"column":105}},"30":{"start":{"line":52,"column":6},"end":{"line":52,"column":106}},"31":{"start":{"line":54,"column":6},"end":{"line":54,"column":120}},"32":{"start":{"line":54,"column":37},"end":{"line":54,"column":120}},"33":{"start":{"line":55,"column":6},"end":{"line":55,"column":16}},"34":{"start":{"line":60,"column":4},"end":{"line":69,"column":5}},"35":{"start":{"line":61,"column":6},"end":{"line":61,"column":94}},"36":{"start":{"line":61,"column":21},"end":{"line":61,"column":94}},"37":{"start":{"line":63,"column":21},"end":{"line":63,"column":55}},"38":{"start":{"line":64,"column":21},"end":{"line":64,"column":74}},"39":{"start":{"line":66,"column":6},"end":{"line":66,"column":41}},"40":{"start":{"line":68,"column":6},"end":{"line":68,"column":16}},"41":{"start":{"line":73,"column":4},"end":{"line":82,"column":5}},"42":{"start":{"line":74,"column":6},"end":{"line":74,"column":94}},"43":{"start":{"line":74,"column":21},"end":{"line":74,"column":94}},"44":{"start":{"line":75,"column":23},"end":{"line":75,"column":65}},"45":{"start":{"line":76,"column":6},"end":{"line":78,"column":7}},"46":{"start":{"line":77,"column":8},"end":{"line":77,"column":76}},"47":{"start":{"line":79,"column":6},"end":{"line":79,"column":43}},"48":{"start":{"line":81,"column":6},"end":{"line":81,"column":16}},"49":{"start":{"line":86,"column":4},"end":{"line":86,"column":92}},"50":{"start":{"line":86,"column":19},"end":{"line":86,"column":92}},"51":{"start":{"line":87,"column":42},"end":{"line":87,"column":85}},"52":{"start":{"line":88,"column":4},"end":{"line":88,"column":52}},"53":{"start":{"line":89,"column":4},"end":{"line":89,"column":64}},"54":{"start":{"line":93,"column":4},"end":{"line":93,"column":27}},"55":{"start":{"line":94,"column":4},"end":{"line":94,"column":71}},"56":{"start":{"line":9,"column":0},"end":{"line":9,"column":13}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":10,"column":2},"end":{"line":10,"column":7}},"loc":{"start":{"line":10,"column":64},"end":{"line":21,"column":3}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":23,"column":2},"end":{"line":23,"column":7}},"loc":{"start":{"line":23,"column":55},"end":{"line":33,"column":3}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":35,"column":2},"end":{"line":35,"column":7}},"loc":{"start":{"line":35,"column":63},"end":{"line":43,"column":3}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":45,"column":2},"end":{"line":45,"column":7}},"loc":{"start":{"line":45,"column":73},"end":{"line":57,"column":3}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":59,"column":2},"end":{"line":59,"column":7}},"loc":{"start":{"line":59,"column":70},"end":{"line":70,"column":3}}},"5":{"name":"(anonymous_6)","decl":{"start":{"line":72,"column":2},"end":{"line":72,"column":7}},"loc":{"start":{"line":72,"column":64},"end":{"line":83,"column":3}}},"6":{"name":"(anonymous_7)","decl":{"start":{"line":85,"column":2},"end":{"line":85,"column":15}},"loc":{"start":{"line":85,"column":43},"end":{"line":90,"column":3}}},"7":{"name":"(anonymous_8)","decl":{"start":{"line":92,"column":2},"end":{"line":92,"column":8}},"loc":{"start":{"line":92,"column":36},"end":{"line":95,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":16,"column":6},"end":{"line":18,"column":7}},"type":"if","locations":[{"start":{"line":16,"column":6},"end":{"line":18,"column":7}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":24,"column":4},"end":{"line":24,"column":92}},"type":"if","locations":[{"start":{"line":24,"column":4},"end":{"line":24,"column":92}},{"start":{},"end":{}}]},"2":{"loc":{"start":{"line":37,"column":6},"end":{"line":37,"column":94}},"type":"if","locations":[{"start":{"line":37,"column":6},"end":{"line":37,"column":94}},{"start":{},"end":{}}]},"3":{"loc":{"start":{"line":47,"column":6},"end":{"line":47,"column":94}},"type":"if","locations":[{"start":{"line":47,"column":6},"end":{"line":47,"column":94}},{"start":{},"end":{}}]},"4":{"loc":{"start":{"line":54,"column":6},"end":{"line":54,"column":120}},"type":"if","locations":[{"start":{"line":54,"column":6},"end":{"line":54,"column":120}},{"start":{},"end":{}}]},"5":{"loc":{"start":{"line":61,"column":6},"end":{"line":61,"column":94}},"type":"if","locations":[{"start":{"line":61,"column":6},"end":{"line":61,"column":94}},{"start":{},"end":{}}]},"6":{"loc":{"start":{"line":74,"column":6},"end":{"line":74,"column":94}},"type":"if","locations":[{"start":{"line":74,"column":6},"end":{"line":74,"column":94}},{"start":{},"end":{}}]},"7":{"loc":{"start":{"line":76,"column":6},"end":{"line":78,"column":7}},"type":"if","locations":[{"start":{"line":76,"column":6},"end":{"line":78,"column":7}},{"start":{},"end":{}}]},"8":{"loc":{"start":{"line":76,"column":10},"end":{"line":76,"column":44}},"type":"binary-expr","locations":[{"start":{"line":76,"column":10},"end":{"line":76,"column":19}},{"start":{"line":76,"column":23},"end":{"line":76,"column":44}}]},"9":{"loc":{"start":{"line":86,"column":4},"end":{"line":86,"column":92}},"type":"if","locations":[{"start":{"line":86,"column":4},"end":{"line":86,"column":92}},{"start":{},"end":{}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":1},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/dtos/article.dto.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/dtos/article.dto.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":24}},"1":{"start":{"line":4,"column":13},"end":{"line":10,"column":3}},"2":{"start":{"line":14,"column":13},"end":{"line":21,"column":3}},"3":{"start":{"line":25,"column":13},"end":{"line":37,"column":3}},"4":{"start":{"line":30,"column":21},"end":{"line":30,"column":28}},"5":{"start":{"line":35,"column":21},"end":{"line":35,"column":42}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":30,"column":12},"end":{"line":30,"column":13}},"loc":{"start":{"line":30,"column":21},"end":{"line":30,"column":28}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":35,"column":12},"end":{"line":35,"column":13}},"loc":{"start":{"line":35,"column":21},"end":{"line":35,"column":42}}}},"branchMap":{"0":{"loc":{"start":{"line":35,"column":21},"end":{"line":35,"column":42}},"type":"binary-expr","locations":[{"start":{"line":35,"column":21},"end":{"line":35,"column":28}},{"start":{"line":35,"column":32},"end":{"line":35,"column":42}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":0,"5":0},"f":{"0":0,"1":0},"b":{"0":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/dtos/product.dto.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/dtos/product.dto.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":24}},"1":{"start":{"line":5,"column":13},"end":{"line":10,"column":3}},"2":{"start":{"line":14,"column":13},"end":{"line":19,"column":3}},"3":{"start":{"line":23,"column":13},"end":{"line":27,"column":3}},"4":{"start":{"line":24,"column":64},"end":{"line":24,"column":69}},"5":{"start":{"line":25,"column":68},"end":{"line":25,"column":85}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":24,"column":57},"end":{"line":24,"column":58}},"loc":{"start":{"line":24,"column":64},"end":{"line":24,"column":69}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":25,"column":61},"end":{"line":25,"column":62}},"loc":{"start":{"line":25,"column":68},"end":{"line":25,"column":85}}}},"branchMap":{"0":{"loc":{"start":{"line":25,"column":68},"end":{"line":25,"column":85}},"type":"binary-expr","locations":[{"start":{"line":25,"column":68},"end":{"line":25,"column":73}},{"start":{"line":25,"column":77},"end":{"line":25,"column":85}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1},"f":{"0":1,"1":1},"b":{"0":[1,1]}} +,"/home/baturs/4-sprint-mission/mission 9/src/dtos/user.dto.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/dtos/user.dto.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":24}},"1":{"start":{"line":4,"column":13},"end":{"line":8,"column":3}},"2":{"start":{"line":12,"column":13},"end":{"line":15,"column":3}},"3":{"start":{"line":19,"column":13},"end":{"line":22,"column":3}},"4":{"start":{"line":26,"column":13},"end":{"line":28,"column":3}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1,"2":1,"3":1,"4":1},"f":{},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/lib/constants.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/lib/constants.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":28}},"1":{"start":{"line":3,"column":0},"end":{"line":3,"column":16}},"2":{"start":{"line":5,"column":17},"end":{"line":5,"column":54}},"3":{"start":{"line":15,"column":2},"end":{"line":15,"column":10}},"4":{"start":{"line":6,"column":13},"end":{"line":6,"column":37}},"5":{"start":{"line":16,"column":2},"end":{"line":16,"column":6}},"6":{"start":{"line":8,"column":2},"end":{"line":8,"column":71}},"7":{"start":{"line":17,"column":2},"end":{"line":17,"column":25}},"8":{"start":{"line":10,"column":2},"end":{"line":10,"column":73}},"9":{"start":{"line":18,"column":2},"end":{"line":18,"column":26}},"10":{"start":{"line":11,"column":33},"end":{"line":11,"column":47}},"11":{"start":{"line":19,"column":2},"end":{"line":19,"column":26}},"12":{"start":{"line":12,"column":34},"end":{"line":12,"column":49}},"13":{"start":{"line":20,"column":2},"end":{"line":20,"column":27}}},"fnMap":{},"branchMap":{"0":{"loc":{"start":{"line":5,"column":17},"end":{"line":5,"column":54}},"type":"binary-expr","locations":[{"start":{"line":5,"column":17},"end":{"line":5,"column":37}},{"start":{"line":5,"column":41},"end":{"line":5,"column":54}}]},"1":{"loc":{"start":{"line":6,"column":13},"end":{"line":6,"column":37}},"type":"binary-expr","locations":[{"start":{"line":6,"column":13},"end":{"line":6,"column":29}},{"start":{"line":6,"column":33},"end":{"line":6,"column":37}}]},"2":{"loc":{"start":{"line":8,"column":2},"end":{"line":8,"column":71}},"type":"binary-expr","locations":[{"start":{"line":8,"column":2},"end":{"line":8,"column":37}},{"start":{"line":8,"column":41},"end":{"line":8,"column":71}}]},"3":{"loc":{"start":{"line":10,"column":2},"end":{"line":10,"column":73}},"type":"binary-expr","locations":[{"start":{"line":10,"column":2},"end":{"line":10,"column":38}},{"start":{"line":10,"column":42},"end":{"line":10,"column":73}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1},"f":{},"b":{"0":[1,0],"1":[1,0],"2":[1,0],"3":[1,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/lib/cookieUtil.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/lib/cookieUtil.ts","statementMap":{"0":{"start":{"line":4,"column":0},"end":{"line":4,"column":16}},"1":{"start":{"line":19,"column":0},"end":{"line":19,"column":16}},"2":{"start":{"line":2,"column":0},"end":{"line":2,"column":92}},"3":{"start":{"line":5,"column":2},"end":{"line":9,"column":5}},"4":{"start":{"line":11,"column":2},"end":{"line":16,"column":5}},"5":{"start":{"line":20,"column":2},"end":{"line":20,"column":44}},"6":{"start":{"line":21,"column":2},"end":{"line":21,"column":45}}},"fnMap":{"0":{"name":"setTokenCookies","decl":{"start":{"line":4,"column":16},"end":{"line":4,"column":31}},"loc":{"start":{"line":4,"column":88},"end":{"line":17,"column":1}}},"1":{"name":"clearTokenCookies","decl":{"start":{"line":19,"column":16},"end":{"line":19,"column":33}},"loc":{"start":{"line":19,"column":47},"end":{"line":22,"column":1}}}},"branchMap":{},"s":{"0":1,"1":1,"2":1,"3":0,"4":0,"5":0,"6":0},"f":{"0":0,"1":0},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/lib/prisma.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/lib/prisma.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":46}},"1":{"start":{"line":3,"column":15},"end":{"line":3,"column":33}},"2":{"start":{"line":5,"column":0},"end":{"line":5,"column":22}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1,"2":1},"f":{},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/lib/token.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/lib/token.ts","statementMap":{"0":{"start":{"line":27,"column":9},"end":{"line":27,"column":23}},"1":{"start":{"line":27,"column":25},"end":{"line":27,"column":42}},"2":{"start":{"line":27,"column":44},"end":{"line":27,"column":62}},"3":{"start":{"line":1,"column":1},"end":{"line":1,"column":32}},"4":{"start":{"line":2,"column":0},"end":{"line":2,"column":null}},"5":{"start":{"line":8,"column":22},"end":{"line":10,"column":4}},"6":{"start":{"line":11,"column":23},"end":{"line":13,"column":4}},"7":{"start":{"line":14,"column":2},"end":{"line":14,"column":39}},"8":{"start":{"line":18,"column":18},"end":{"line":18,"column":60}},"9":{"start":{"line":19,"column":2},"end":{"line":19,"column":33}},"10":{"start":{"line":23,"column":18},"end":{"line":23,"column":61}},"11":{"start":{"line":24,"column":2},"end":{"line":24,"column":33}}},"fnMap":{"0":{"name":"generateTokens","decl":{"start":{"line":7,"column":9},"end":{"line":7,"column":23}},"loc":{"start":{"line":7,"column":38},"end":{"line":15,"column":1}}},"1":{"name":"verifyAccessToken","decl":{"start":{"line":17,"column":9},"end":{"line":17,"column":26}},"loc":{"start":{"line":17,"column":40},"end":{"line":20,"column":1}}},"2":{"name":"verifyRefreshToken","decl":{"start":{"line":22,"column":9},"end":{"line":22,"column":27}},"loc":{"start":{"line":22,"column":41},"end":{"line":25,"column":1}}}},"branchMap":{},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0},"f":{"0":0,"1":0,"2":0},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/lib/passport/index.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/lib/passport/index.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":32}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":48}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":74}},"3":{"start":{"line":5,"column":0},"end":{"line":5,"column":37}},"4":{"start":{"line":6,"column":0},"end":{"line":6,"column":50}},"5":{"start":{"line":7,"column":0},"end":{"line":7,"column":52}},"6":{"start":{"line":9,"column":0},"end":{"line":9,"column":24}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1},"f":{},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/lib/passport/jwtStrategy.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/lib/passport/jwtStrategy.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":55}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":31}},"2":{"start":{"line":5,"column":0},"end":{"line":5,"column":null}},"3":{"start":{"line":16,"column":27},"end":{"line":19,"column":2}},"4":{"start":{"line":17,"column":36},"end":{"line":17,"column":73}},"5":{"start":{"line":21,"column":28},"end":{"line":24,"column":2}},"6":{"start":{"line":22,"column":36},"end":{"line":22,"column":74}},"7":{"start":{"line":27,"column":2},"end":{"line":34,"column":3}},"8":{"start":{"line":28,"column":17},"end":{"line":30,"column":6}},"9":{"start":{"line":31,"column":4},"end":{"line":31,"column":21}},"10":{"start":{"line":33,"column":4},"end":{"line":33,"column":23}},"11":{"start":{"line":37,"column":13},"end":{"line":40,"column":2}},"12":{"start":{"line":42,"column":13},"end":{"line":45,"column":2}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":17,"column":18},"end":{"line":17,"column":19}},"loc":{"start":{"line":17,"column":36},"end":{"line":17,"column":73}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":22,"column":18},"end":{"line":22,"column":19}},"loc":{"start":{"line":22,"column":36},"end":{"line":22,"column":74}}},"2":{"name":"jwtVerify","decl":{"start":{"line":26,"column":15},"end":{"line":26,"column":24}},"loc":{"start":{"line":26,"column":68},"end":{"line":35,"column":1}}}},"branchMap":{},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":0,"7":0,"8":0,"9":0,"10":0,"11":1,"12":1},"f":{"0":1,"1":0,"2":0},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/lib/passport/localStrategy.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/lib/passport/localStrategy.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":59}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":28}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":31}},"3":{"start":{"line":5,"column":13},"end":{"line":27,"column":2}},"4":{"start":{"line":11,"column":4},"end":{"line":25,"column":5}},"5":{"start":{"line":12,"column":19},"end":{"line":12,"column":69}},"6":{"start":{"line":13,"column":6},"end":{"line":15,"column":7}},"7":{"start":{"line":14,"column":8},"end":{"line":14,"column":63}},"8":{"start":{"line":17,"column":30},"end":{"line":17,"column":75}},"9":{"start":{"line":18,"column":6},"end":{"line":20,"column":7}},"10":{"start":{"line":19,"column":8},"end":{"line":19,"column":66}},"11":{"start":{"line":22,"column":6},"end":{"line":22,"column":30}},"12":{"start":{"line":24,"column":6},"end":{"line":24,"column":23}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":10,"column":2},"end":{"line":10,"column":7}},"loc":{"start":{"line":10,"column":34},"end":{"line":26,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":13,"column":6},"end":{"line":15,"column":7}},"type":"if","locations":[{"start":{"line":13,"column":6},"end":{"line":15,"column":7}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":18,"column":6},"end":{"line":20,"column":7}},"type":"if","locations":[{"start":{"line":18,"column":6},"end":{"line":20,"column":7}},{"start":{},"end":{}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0},"f":{"0":0},"b":{"0":[0,0],"1":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/middlewares/errorHandler.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/middlewares/errorHandler.ts","statementMap":{"0":{"start":{"line":9,"column":0},"end":{"line":9,"column":16}},"1":{"start":{"line":1,"column":0},"end":{"line":1,"column":24}},"2":{"start":{"line":2,"column":0},"end":{"line":2,"column":37}},"3":{"start":{"line":10,"column":2},"end":{"line":12,"column":3}},"4":{"start":{"line":11,"column":4},"end":{"line":11,"column":74}},"5":{"start":{"line":14,"column":2},"end":{"line":16,"column":3}},"6":{"start":{"line":15,"column":4},"end":{"line":15,"column":80}},"7":{"start":{"line":18,"column":2},"end":{"line":18,"column":41}},"8":{"start":{"line":19,"column":2},"end":{"line":21,"column":46}}},"fnMap":{"0":{"name":"errorHandler","decl":{"start":{"line":9,"column":16},"end":{"line":9,"column":28}},"loc":{"start":{"line":9,"column":96},"end":{"line":22,"column":1}}}},"branchMap":{"0":{"loc":{"start":{"line":10,"column":2},"end":{"line":12,"column":3}},"type":"if","locations":[{"start":{"line":10,"column":2},"end":{"line":12,"column":3}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":14,"column":2},"end":{"line":16,"column":3}},"type":"if","locations":[{"start":{"line":14,"column":2},"end":{"line":16,"column":3}},{"start":{},"end":{}}]}},"s":{"0":1,"1":1,"2":1,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0},"f":{"0":0},"b":{"0":[0,0],"1":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/repositories/alertRepository.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/repositories/alertRepository.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":35}},"1":{"start":{"line":5,"column":4},"end":{"line":5,"column":41}},"2":{"start":{"line":9,"column":4},"end":{"line":12,"column":7}},"3":{"start":{"line":16,"column":4},"end":{"line":19,"column":7}},"4":{"start":{"line":23,"column":4},"end":{"line":25,"column":7}},"5":{"start":{"line":29,"column":4},"end":{"line":31,"column":7}},"6":{"start":{"line":3,"column":0},"end":{"line":3,"column":13}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":4,"column":2},"end":{"line":4,"column":7}},"loc":{"start":{"line":4,"column":76},"end":{"line":6,"column":3}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":8,"column":2},"end":{"line":8,"column":7}},"loc":{"start":{"line":8,"column":35},"end":{"line":13,"column":3}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":15,"column":2},"end":{"line":15,"column":7}},"loc":{"start":{"line":15,"column":29},"end":{"line":20,"column":3}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":22,"column":2},"end":{"line":22,"column":7}},"loc":{"start":{"line":22,"column":34},"end":{"line":26,"column":3}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":28,"column":2},"end":{"line":28,"column":7}},"loc":{"start":{"line":28,"column":27},"end":{"line":32,"column":3}}}},"branchMap":{},"s":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":0,"6":1},"f":{"0":0,"1":0,"2":0,"3":0,"4":0},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/repositories/articleRepository.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/repositories/articleRepository.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":35}},"1":{"start":{"line":6,"column":4},"end":{"line":6,"column":43}},"2":{"start":{"line":10,"column":4},"end":{"line":16,"column":7}},"3":{"start":{"line":20,"column":4},"end":{"line":23,"column":7}},"4":{"start":{"line":27,"column":61},"end":{"line":27,"column":63}},"5":{"start":{"line":28,"column":4},"end":{"line":28,"column":64}},"6":{"start":{"line":28,"column":34},"end":{"line":28,"column":64}},"7":{"start":{"line":29,"column":4},"end":{"line":29,"column":70}},"8":{"start":{"line":29,"column":36},"end":{"line":29,"column":70}},"9":{"start":{"line":31,"column":4},"end":{"line":31,"column":70}},"10":{"start":{"line":35,"column":4},"end":{"line":35,"column":51}},"11":{"start":{"line":4,"column":0},"end":{"line":4,"column":13}},"12":{"start":{"line":39,"column":0},"end":{"line":39,"column":39}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":5,"column":2},"end":{"line":5,"column":7}},"loc":{"start":{"line":5,"column":78},"end":{"line":7,"column":3}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":9,"column":2},"end":{"line":9,"column":7}},"loc":{"start":{"line":9,"column":76},"end":{"line":17,"column":3}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":19,"column":2},"end":{"line":19,"column":7}},"loc":{"start":{"line":19,"column":27},"end":{"line":24,"column":3}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":26,"column":2},"end":{"line":26,"column":7}},"loc":{"start":{"line":26,"column":77},"end":{"line":32,"column":3}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":34,"column":2},"end":{"line":34,"column":7}},"loc":{"start":{"line":34,"column":32},"end":{"line":36,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":28,"column":4},"end":{"line":28,"column":64}},"type":"if","locations":[{"start":{"line":28,"column":4},"end":{"line":28,"column":64}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":29,"column":4},"end":{"line":29,"column":70}},"type":"if","locations":[{"start":{"line":29,"column":4},"end":{"line":29,"column":70}},{"start":{},"end":{}}]}},"s":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":1,"12":1},"f":{"0":0,"1":0,"2":0,"3":0,"4":0},"b":{"0":[0,0],"1":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/repositories/commentRepository.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/repositories/commentRepository.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":35}},"1":{"start":{"line":5,"column":4},"end":{"line":7,"column":7}},"2":{"start":{"line":11,"column":4},"end":{"line":13,"column":7}},"3":{"start":{"line":17,"column":4},"end":{"line":17,"column":67}},"4":{"start":{"line":21,"column":4},"end":{"line":24,"column":7}},"5":{"start":{"line":28,"column":4},"end":{"line":28,"column":63}},"6":{"start":{"line":32,"column":4},"end":{"line":38,"column":7}},"7":{"start":{"line":42,"column":4},"end":{"line":48,"column":7}},"8":{"start":{"line":3,"column":0},"end":{"line":3,"column":13}},"9":{"start":{"line":52,"column":0},"end":{"line":52,"column":39}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":4,"column":2},"end":{"line":4,"column":7}},"loc":{"start":{"line":4,"column":79},"end":{"line":8,"column":3}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":10,"column":2},"end":{"line":10,"column":7}},"loc":{"start":{"line":10,"column":79},"end":{"line":14,"column":3}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":16,"column":2},"end":{"line":16,"column":7}},"loc":{"start":{"line":16,"column":34},"end":{"line":18,"column":3}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":20,"column":2},"end":{"line":20,"column":7}},"loc":{"start":{"line":20,"column":56},"end":{"line":25,"column":3}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":27,"column":2},"end":{"line":27,"column":7}},"loc":{"start":{"line":27,"column":39},"end":{"line":29,"column":3}}},"5":{"name":"(anonymous_6)","decl":{"start":{"line":31,"column":2},"end":{"line":31,"column":7}},"loc":{"start":{"line":31,"column":62},"end":{"line":39,"column":3}}},"6":{"name":"(anonymous_7)","decl":{"start":{"line":41,"column":2},"end":{"line":41,"column":7}},"loc":{"start":{"line":41,"column":62},"end":{"line":49,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":35,"column":12},"end":{"line":35,"column":26}},"type":"cond-expr","locations":[{"start":{"line":35,"column":21},"end":{"line":35,"column":22}},{"start":{"line":35,"column":25},"end":{"line":35,"column":26}}]},"1":{"loc":{"start":{"line":36,"column":10},"end":{"line":36,"column":46}},"type":"binary-expr","locations":[{"start":{"line":36,"column":10},"end":{"line":36,"column":16}},{"start":{"line":36,"column":20},"end":{"line":36,"column":46}}]},"2":{"loc":{"start":{"line":45,"column":12},"end":{"line":45,"column":26}},"type":"cond-expr","locations":[{"start":{"line":45,"column":21},"end":{"line":45,"column":22}},{"start":{"line":45,"column":25},"end":{"line":45,"column":26}}]},"3":{"loc":{"start":{"line":46,"column":10},"end":{"line":46,"column":46}},"type":"binary-expr","locations":[{"start":{"line":46,"column":10},"end":{"line":46,"column":16}},{"start":{"line":46,"column":20},"end":{"line":46,"column":46}}]}},"s":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":1,"9":1},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/repositories/likeRepository.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/repositories/likeRepository.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":35}},"1":{"start":{"line":5,"column":4},"end":{"line":5,"column":67}},"2":{"start":{"line":9,"column":4},"end":{"line":9,"column":67}},"3":{"start":{"line":13,"column":4},"end":{"line":15,"column":7}},"4":{"start":{"line":19,"column":4},"end":{"line":21,"column":7}},"5":{"start":{"line":25,"column":4},"end":{"line":28,"column":7}},"6":{"start":{"line":32,"column":4},"end":{"line":35,"column":7}},"7":{"start":{"line":39,"column":4},"end":{"line":41,"column":7}},"8":{"start":{"line":45,"column":4},"end":{"line":47,"column":7}},"9":{"start":{"line":51,"column":4},"end":{"line":56,"column":7}},"10":{"start":{"line":60,"column":4},"end":{"line":65,"column":7}},"11":{"start":{"line":69,"column":18},"end":{"line":82,"column":6}},"12":{"start":{"line":83,"column":4},"end":{"line":83,"column":42}},"13":{"start":{"line":83,"column":31},"end":{"line":83,"column":40}},"14":{"start":{"line":3,"column":0},"end":{"line":3,"column":13}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":4,"column":2},"end":{"line":4,"column":7}},"loc":{"start":{"line":4,"column":37},"end":{"line":6,"column":3}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":8,"column":2},"end":{"line":8,"column":7}},"loc":{"start":{"line":8,"column":37},"end":{"line":10,"column":3}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":12,"column":2},"end":{"line":12,"column":7}},"loc":{"start":{"line":12,"column":57},"end":{"line":16,"column":3}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":18,"column":2},"end":{"line":18,"column":7}},"loc":{"start":{"line":18,"column":57},"end":{"line":22,"column":3}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":24,"column":2},"end":{"line":24,"column":7}},"loc":{"start":{"line":24,"column":77},"end":{"line":29,"column":3}}},"5":{"name":"(anonymous_6)","decl":{"start":{"line":31,"column":2},"end":{"line":31,"column":7}},"loc":{"start":{"line":31,"column":77},"end":{"line":36,"column":3}}},"6":{"name":"(anonymous_7)","decl":{"start":{"line":38,"column":2},"end":{"line":38,"column":7}},"loc":{"start":{"line":38,"column":59},"end":{"line":42,"column":3}}},"7":{"name":"(anonymous_8)","decl":{"start":{"line":44,"column":2},"end":{"line":44,"column":7}},"loc":{"start":{"line":44,"column":59},"end":{"line":48,"column":3}}},"8":{"name":"(anonymous_9)","decl":{"start":{"line":50,"column":2},"end":{"line":50,"column":7}},"loc":{"start":{"line":50,"column":40},"end":{"line":57,"column":3}}},"9":{"name":"(anonymous_10)","decl":{"start":{"line":59,"column":2},"end":{"line":59,"column":7}},"loc":{"start":{"line":59,"column":40},"end":{"line":66,"column":3}}},"10":{"name":"(anonymous_11)","decl":{"start":{"line":68,"column":2},"end":{"line":68,"column":7}},"loc":{"start":{"line":68,"column":50},"end":{"line":84,"column":3}}},"11":{"name":"(anonymous_12)","decl":{"start":{"line":83,"column":21},"end":{"line":83,"column":22}},"loc":{"start":{"line":83,"column":31},"end":{"line":83,"column":40}}}},"branchMap":{},"s":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":1},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/repositories/productRepository.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/repositories/productRepository.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":35}},"1":{"start":{"line":7,"column":4},"end":{"line":7,"column":43}},"2":{"start":{"line":11,"column":4},"end":{"line":24,"column":7}},"3":{"start":{"line":28,"column":4},"end":{"line":39,"column":7}},"4":{"start":{"line":43,"column":4},"end":{"line":43,"column":58}},"5":{"start":{"line":47,"column":4},"end":{"line":47,"column":52}},"6":{"start":{"line":5,"column":0},"end":{"line":5,"column":13}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":6,"column":2},"end":{"line":6,"column":7}},"loc":{"start":{"line":6,"column":110},"end":{"line":8,"column":3}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":10,"column":2},"end":{"line":10,"column":7}},"loc":{"start":{"line":10,"column":76},"end":{"line":25,"column":3}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":27,"column":2},"end":{"line":27,"column":7}},"loc":{"start":{"line":27,"column":27},"end":{"line":40,"column":3}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":42,"column":2},"end":{"line":42,"column":7}},"loc":{"start":{"line":42,"column":115},"end":{"line":44,"column":3}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":46,"column":2},"end":{"line":46,"column":7}},"loc":{"start":{"line":46,"column":32},"end":{"line":48,"column":3}}}},"branchMap":{},"s":{"0":1,"1":0,"2":1,"3":0,"4":0,"5":0,"6":1},"f":{"0":0,"1":1,"2":0,"3":0,"4":0},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/repositories/userRepository.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/repositories/userRepository.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":35}},"1":{"start":{"line":5,"column":4},"end":{"line":5,"column":56}},"2":{"start":{"line":9,"column":4},"end":{"line":12,"column":7}},"3":{"start":{"line":16,"column":4},"end":{"line":16,"column":71}},"4":{"start":{"line":20,"column":4},"end":{"line":20,"column":55}},"5":{"start":{"line":24,"column":4},"end":{"line":27,"column":7}},"6":{"start":{"line":3,"column":0},"end":{"line":3,"column":13}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":4,"column":2},"end":{"line":4,"column":7}},"loc":{"start":{"line":4,"column":33},"end":{"line":6,"column":3}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":8,"column":2},"end":{"line":8,"column":7}},"loc":{"start":{"line":8,"column":27},"end":{"line":13,"column":3}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":15,"column":2},"end":{"line":15,"column":7}},"loc":{"start":{"line":15,"column":68},"end":{"line":17,"column":3}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":19,"column":2},"end":{"line":19,"column":7}},"loc":{"start":{"line":19,"column":99},"end":{"line":21,"column":3}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":23,"column":2},"end":{"line":23,"column":7}},"loc":{"start":{"line":23,"column":43},"end":{"line":28,"column":3}}}},"branchMap":{},"s":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":0,"6":1},"f":{"0":0,"1":0,"2":0,"3":0,"4":0},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/routers/alertRouter.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/routers/alertRouter.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":30}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":39}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":65}},"3":{"start":{"line":5,"column":15},"end":{"line":5,"column":31}},"4":{"start":{"line":6,"column":19},"end":{"line":6,"column":40}},"5":{"start":{"line":8,"column":0},"end":{"line":8,"column":92}},"6":{"start":{"line":10,"column":0},"end":{"line":10,"column":108}},"7":{"start":{"line":12,"column":0},"end":{"line":12,"column":22}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1},"f":{},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/routers/articleRouter.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/routers/articleRouter.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":30}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":39}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":69}},"3":{"start":{"line":5,"column":15},"end":{"line":5,"column":31}},"4":{"start":{"line":6,"column":19},"end":{"line":6,"column":42}},"5":{"start":{"line":8,"column":0},"end":{"line":8,"column":95}},"6":{"start":{"line":9,"column":0},"end":{"line":9,"column":99}},"7":{"start":{"line":10,"column":0},"end":{"line":10,"column":100}},"8":{"start":{"line":12,"column":0},"end":{"line":12,"column":33}},"9":{"start":{"line":13,"column":0},"end":{"line":13,"column":38}},"10":{"start":{"line":15,"column":0},"end":{"line":15,"column":22}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1},"f":{},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/routers/commentRouter.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/routers/commentRouter.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":30}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":39}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":69}},"3":{"start":{"line":5,"column":15},"end":{"line":5,"column":31}},"4":{"start":{"line":6,"column":19},"end":{"line":6,"column":42}},"5":{"start":{"line":9,"column":0},"end":{"line":9,"column":121}},"6":{"start":{"line":10,"column":0},"end":{"line":10,"column":121}},"7":{"start":{"line":11,"column":0},"end":{"line":11,"column":106}},"8":{"start":{"line":12,"column":0},"end":{"line":12,"column":107}},"9":{"start":{"line":15,"column":0},"end":{"line":15,"column":59}},"10":{"start":{"line":16,"column":0},"end":{"line":16,"column":59}},"11":{"start":{"line":18,"column":0},"end":{"line":18,"column":22}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1},"f":{},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/routers/index.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/routers/index.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":30}},"1":{"start":{"line":3,"column":0},"end":{"line":3,"column":38}},"2":{"start":{"line":4,"column":0},"end":{"line":4,"column":44}},"3":{"start":{"line":5,"column":0},"end":{"line":5,"column":44}},"4":{"start":{"line":6,"column":0},"end":{"line":6,"column":44}},"5":{"start":{"line":7,"column":0},"end":{"line":7,"column":38}},"6":{"start":{"line":8,"column":0},"end":{"line":8,"column":40}},"7":{"start":{"line":9,"column":0},"end":{"line":9,"column":40}},"8":{"start":{"line":11,"column":15},"end":{"line":11,"column":31}},"9":{"start":{"line":13,"column":0},"end":{"line":13,"column":33}},"10":{"start":{"line":14,"column":0},"end":{"line":14,"column":39}},"11":{"start":{"line":15,"column":0},"end":{"line":15,"column":39}},"12":{"start":{"line":16,"column":0},"end":{"line":16,"column":39}},"13":{"start":{"line":17,"column":0},"end":{"line":17,"column":33}},"14":{"start":{"line":18,"column":0},"end":{"line":18,"column":24}},"15":{"start":{"line":19,"column":0},"end":{"line":19,"column":35}},"16":{"start":{"line":21,"column":0},"end":{"line":21,"column":22}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1,"14":1,"15":1,"16":1},"f":{},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/routers/likeRouter.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/routers/likeRouter.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":30}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":39}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":63}},"3":{"start":{"line":5,"column":15},"end":{"line":5,"column":31}},"4":{"start":{"line":6,"column":19},"end":{"line":6,"column":39}},"5":{"start":{"line":8,"column":0},"end":{"line":8,"column":112}},"6":{"start":{"line":9,"column":0},"end":{"line":9,"column":112}},"7":{"start":{"line":10,"column":0},"end":{"line":10,"column":112}},"8":{"start":{"line":11,"column":0},"end":{"line":11,"column":112}},"9":{"start":{"line":13,"column":0},"end":{"line":13,"column":22}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1},"f":{},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/routers/photoRouter.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/routers/photoRouter.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":30}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":28}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":39}},"3":{"start":{"line":4,"column":0},"end":{"line":4,"column":65}},"4":{"start":{"line":6,"column":15},"end":{"line":6,"column":31}},"5":{"start":{"line":7,"column":15},"end":{"line":7,"column":43}},"6":{"start":{"line":8,"column":19},"end":{"line":8,"column":40}},"7":{"start":{"line":10,"column":0},"end":{"line":15,"column":2}},"8":{"start":{"line":17,"column":0},"end":{"line":17,"column":22}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1},"f":{},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/routers/productRouter.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/routers/productRouter.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":30}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":39}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":69}},"3":{"start":{"line":5,"column":15},"end":{"line":5,"column":31}},"4":{"start":{"line":6,"column":19},"end":{"line":6,"column":42}},"5":{"start":{"line":9,"column":0},"end":{"line":9,"column":95}},"6":{"start":{"line":10,"column":0},"end":{"line":10,"column":99}},"7":{"start":{"line":11,"column":0},"end":{"line":11,"column":100}},"8":{"start":{"line":14,"column":0},"end":{"line":14,"column":33}},"9":{"start":{"line":15,"column":0},"end":{"line":15,"column":38}},"10":{"start":{"line":17,"column":0},"end":{"line":17,"column":22}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1},"f":{},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/routers/userRouter.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/routers/userRouter.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":30}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":39}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":63}},"3":{"start":{"line":5,"column":15},"end":{"line":5,"column":31}},"4":{"start":{"line":6,"column":19},"end":{"line":6,"column":39}},"5":{"start":{"line":8,"column":0},"end":{"line":8,"column":46}},"6":{"start":{"line":9,"column":0},"end":{"line":9,"column":92}},"7":{"start":{"line":10,"column":0},"end":{"line":10,"column":102}},"8":{"start":{"line":11,"column":0},"end":{"line":11,"column":124}},"9":{"start":{"line":12,"column":0},"end":{"line":12,"column":118}},"10":{"start":{"line":13,"column":0},"end":{"line":13,"column":104}},"11":{"start":{"line":14,"column":0},"end":{"line":14,"column":110}},"12":{"start":{"line":15,"column":0},"end":{"line":15,"column":42}},"13":{"start":{"line":17,"column":0},"end":{"line":17,"column":22}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1},"f":{},"b":{}} +,"/home/baturs/4-sprint-mission/mission 9/src/services/alertService.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/services/alertService.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":66}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":37}},"2":{"start":{"line":5,"column":10},"end":{"line":5,"column":39}},"3":{"start":{"line":8,"column":18},"end":{"line":8,"column":72}},"4":{"start":{"line":10,"column":15},"end":{"line":10,"column":22}},"5":{"start":{"line":11,"column":4},"end":{"line":11,"column":52}},"6":{"start":{"line":13,"column":4},"end":{"line":13,"column":17}},"7":{"start":{"line":17,"column":4},"end":{"line":17,"column":42}},"8":{"start":{"line":21,"column":18},"end":{"line":21,"column":51}},"9":{"start":{"line":23,"column":4},"end":{"line":23,"column":29}},"10":{"start":{"line":23,"column":16},"end":{"line":23,"column":29}},"11":{"start":{"line":25,"column":4},"end":{"line":27,"column":5}},"12":{"start":{"line":26,"column":6},"end":{"line":26,"column":19}},"13":{"start":{"line":29,"column":4},"end":{"line":29,"column":40}},"14":{"start":{"line":31,"column":4},"end":{"line":31,"column":16}},"15":{"start":{"line":35,"column":4},"end":{"line":35,"column":41}},"16":{"start":{"line":4,"column":0},"end":{"line":4,"column":13}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":4,"column":0},"end":{"line":4,"column":13}},"loc":{"start":{"line":4,"column":0},"end":{"line":37,"column":1}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":7,"column":2},"end":{"line":7,"column":7}},"loc":{"start":{"line":7,"column":61},"end":{"line":14,"column":3}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":16,"column":2},"end":{"line":16,"column":7}},"loc":{"start":{"line":16,"column":27},"end":{"line":18,"column":3}}},"3":{"name":"(anonymous_3)","decl":{"start":{"line":20,"column":2},"end":{"line":20,"column":7}},"loc":{"start":{"line":20,"column":44},"end":{"line":32,"column":3}}},"4":{"name":"(anonymous_4)","decl":{"start":{"line":34,"column":2},"end":{"line":34,"column":7}},"loc":{"start":{"line":34,"column":34},"end":{"line":36,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":23,"column":4},"end":{"line":23,"column":29}},"type":"if","locations":[{"start":{"line":23,"column":4},"end":{"line":23,"column":29}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":25,"column":4},"end":{"line":27,"column":5}},"type":"if","locations":[{"start":{"line":25,"column":4},"end":{"line":27,"column":5}},{"start":{},"end":{}}]}},"s":{"0":1,"1":1,"2":3,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":1},"f":{"0":3,"1":0,"2":0,"3":0,"4":0},"b":{"0":[0,0],"1":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/services/articleService.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/services/articleService.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":70}},"1":{"start":{"line":6,"column":10},"end":{"line":6,"column":41}},"2":{"start":{"line":9,"column":4},"end":{"line":9,"column":56}},"3":{"start":{"line":13,"column":44},"end":{"line":20,"column":10}},"4":{"start":{"line":22,"column":4},"end":{"line":22,"column":70}},"5":{"start":{"line":26,"column":4},"end":{"line":26,"column":34}},"6":{"start":{"line":30,"column":20},"end":{"line":30,"column":55}},"7":{"start":{"line":31,"column":4},"end":{"line":31,"column":47}},"8":{"start":{"line":31,"column":18},"end":{"line":31,"column":47}},"9":{"start":{"line":32,"column":4},"end":{"line":32,"column":64}},"10":{"start":{"line":32,"column":35},"end":{"line":32,"column":64}},"11":{"start":{"line":34,"column":4},"end":{"line":34,"column":53}},"12":{"start":{"line":38,"column":20},"end":{"line":38,"column":55}},"13":{"start":{"line":39,"column":4},"end":{"line":39,"column":47}},"14":{"start":{"line":39,"column":18},"end":{"line":39,"column":47}},"15":{"start":{"line":40,"column":4},"end":{"line":40,"column":64}},"16":{"start":{"line":40,"column":35},"end":{"line":40,"column":64}},"17":{"start":{"line":42,"column":4},"end":{"line":42,"column":45}},"18":{"start":{"line":5,"column":0},"end":{"line":5,"column":13}},"19":{"start":{"line":46,"column":0},"end":{"line":46,"column":36}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":5,"column":0},"end":{"line":5,"column":13}},"loc":{"start":{"line":5,"column":0},"end":{"line":44,"column":1}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":8,"column":2},"end":{"line":8,"column":7}},"loc":{"start":{"line":8,"column":53},"end":{"line":10,"column":3}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":12,"column":2},"end":{"line":12,"column":7}},"loc":{"start":{"line":12,"column":57},"end":{"line":23,"column":3}}},"3":{"name":"(anonymous_3)","decl":{"start":{"line":25,"column":2},"end":{"line":25,"column":7}},"loc":{"start":{"line":25,"column":28},"end":{"line":27,"column":3}}},"4":{"name":"(anonymous_4)","decl":{"start":{"line":29,"column":2},"end":{"line":29,"column":7}},"loc":{"start":{"line":29,"column":72},"end":{"line":35,"column":3}}},"5":{"name":"(anonymous_5)","decl":{"start":{"line":37,"column":2},"end":{"line":37,"column":7}},"loc":{"start":{"line":37,"column":48},"end":{"line":43,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":13,"column":44},"end":{"line":20,"column":10}},"type":"cond-expr","locations":[{"start":{"line":14,"column":8},"end":{"line":19,"column":null}},{"start":{"line":20,"column":8},"end":{"line":20,"column":10}}]},"1":{"loc":{"start":{"line":31,"column":4},"end":{"line":31,"column":47}},"type":"if","locations":[{"start":{"line":31,"column":4},"end":{"line":31,"column":47}},{"start":{},"end":{}}]},"2":{"loc":{"start":{"line":32,"column":4},"end":{"line":32,"column":64}},"type":"if","locations":[{"start":{"line":32,"column":4},"end":{"line":32,"column":64}},{"start":{},"end":{}}]},"3":{"loc":{"start":{"line":39,"column":4},"end":{"line":39,"column":47}},"type":"if","locations":[{"start":{"line":39,"column":4},"end":{"line":39,"column":47}},{"start":{},"end":{}}]},"4":{"loc":{"start":{"line":40,"column":4},"end":{"line":40,"column":64}},"type":"if","locations":[{"start":{"line":40,"column":4},"end":{"line":40,"column":64}},{"start":{},"end":{}}]}},"s":{"0":1,"1":2,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":1,"19":1},"f":{"0":2,"1":0,"2":0,"3":0,"4":0,"5":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/services/commentService.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/services/commentService.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":70}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":70}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":70}},"3":{"start":{"line":4,"column":0},"end":{"line":4,"column":56}},"4":{"start":{"line":7,"column":10},"end":{"line":7,"column":41}},"5":{"start":{"line":8,"column":10},"end":{"line":8,"column":48}},"6":{"start":{"line":9,"column":10},"end":{"line":9,"column":48}},"7":{"start":{"line":10,"column":10},"end":{"line":10,"column":44}},"8":{"start":{"line":17,"column":20},"end":{"line":17,"column":62}},"9":{"start":{"line":18,"column":4},"end":{"line":20,"column":5}},"10":{"start":{"line":19,"column":6},"end":{"line":19,"column":43}},"11":{"start":{"line":22,"column":20},"end":{"line":25,"column":null}},"12":{"start":{"line":28,"column":4},"end":{"line":34,"column":5}},"13":{"start":{"line":29,"column":6},"end":{"line":33,"column":8}},"14":{"start":{"line":36,"column":4},"end":{"line":36,"column":19}},"15":{"start":{"line":44,"column":20},"end":{"line":44,"column":62}},"16":{"start":{"line":45,"column":4},"end":{"line":47,"column":5}},"17":{"start":{"line":46,"column":6},"end":{"line":46,"column":43}},"18":{"start":{"line":49,"column":20},"end":{"line":52,"column":null}},"19":{"start":{"line":55,"column":4},"end":{"line":61,"column":5}},"20":{"start":{"line":56,"column":6},"end":{"line":60,"column":8}},"21":{"start":{"line":63,"column":4},"end":{"line":63,"column":19}},"22":{"start":{"line":67,"column":20},"end":{"line":67,"column":55}},"23":{"start":{"line":68,"column":4},"end":{"line":68,"column":47}},"24":{"start":{"line":68,"column":18},"end":{"line":68,"column":47}},"25":{"start":{"line":69,"column":4},"end":{"line":69,"column":64}},"26":{"start":{"line":69,"column":35},"end":{"line":69,"column":64}},"27":{"start":{"line":70,"column":4},"end":{"line":70,"column":55}},"28":{"start":{"line":74,"column":20},"end":{"line":74,"column":55}},"29":{"start":{"line":75,"column":4},"end":{"line":75,"column":47}},"30":{"start":{"line":75,"column":18},"end":{"line":75,"column":47}},"31":{"start":{"line":76,"column":4},"end":{"line":76,"column":64}},"32":{"start":{"line":76,"column":35},"end":{"line":76,"column":64}},"33":{"start":{"line":77,"column":4},"end":{"line":77,"column":45}},"34":{"start":{"line":81,"column":4},"end":{"line":81,"column":60}},"35":{"start":{"line":85,"column":4},"end":{"line":85,"column":60}},"36":{"start":{"line":6,"column":0},"end":{"line":6,"column":13}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":6,"column":0},"end":{"line":6,"column":13}},"loc":{"start":{"line":6,"column":0},"end":{"line":87,"column":1}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":12,"column":2},"end":{"line":12,"column":7}},"loc":{"start":{"line":15,"column":19},"end":{"line":37,"column":3}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":39,"column":2},"end":{"line":39,"column":7}},"loc":{"start":{"line":42,"column":19},"end":{"line":64,"column":3}}},"3":{"name":"(anonymous_3)","decl":{"start":{"line":66,"column":2},"end":{"line":66,"column":7}},"loc":{"start":{"line":66,"column":72},"end":{"line":71,"column":3}}},"4":{"name":"(anonymous_4)","decl":{"start":{"line":73,"column":2},"end":{"line":73,"column":7}},"loc":{"start":{"line":73,"column":55},"end":{"line":78,"column":3}}},"5":{"name":"(anonymous_5)","decl":{"start":{"line":80,"column":2},"end":{"line":80,"column":7}},"loc":{"start":{"line":80,"column":61},"end":{"line":82,"column":3}}},"6":{"name":"(anonymous_6)","decl":{"start":{"line":84,"column":2},"end":{"line":84,"column":7}},"loc":{"start":{"line":84,"column":61},"end":{"line":86,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":18,"column":4},"end":{"line":20,"column":5}},"type":"if","locations":[{"start":{"line":18,"column":4},"end":{"line":20,"column":5}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":28,"column":4},"end":{"line":34,"column":5}},"type":"if","locations":[{"start":{"line":28,"column":4},"end":{"line":34,"column":5}},{"start":{},"end":{}}]},"2":{"loc":{"start":{"line":28,"column":8},"end":{"line":28,"column":44}},"type":"binary-expr","locations":[{"start":{"line":28,"column":8},"end":{"line":28,"column":15}},{"start":{"line":28,"column":19},"end":{"line":28,"column":44}}]},"3":{"loc":{"start":{"line":45,"column":4},"end":{"line":47,"column":5}},"type":"if","locations":[{"start":{"line":45,"column":4},"end":{"line":47,"column":5}},{"start":{},"end":{}}]},"4":{"loc":{"start":{"line":55,"column":4},"end":{"line":61,"column":5}},"type":"if","locations":[{"start":{"line":55,"column":4},"end":{"line":61,"column":5}},{"start":{},"end":{}}]},"5":{"loc":{"start":{"line":55,"column":8},"end":{"line":55,"column":44}},"type":"binary-expr","locations":[{"start":{"line":55,"column":8},"end":{"line":55,"column":15}},{"start":{"line":55,"column":19},"end":{"line":55,"column":44}}]},"6":{"loc":{"start":{"line":68,"column":4},"end":{"line":68,"column":47}},"type":"if","locations":[{"start":{"line":68,"column":4},"end":{"line":68,"column":47}},{"start":{},"end":{}}]},"7":{"loc":{"start":{"line":69,"column":4},"end":{"line":69,"column":64}},"type":"if","locations":[{"start":{"line":69,"column":4},"end":{"line":69,"column":64}},{"start":{},"end":{}}]},"8":{"loc":{"start":{"line":75,"column":4},"end":{"line":75,"column":47}},"type":"if","locations":[{"start":{"line":75,"column":4},"end":{"line":75,"column":47}},{"start":{},"end":{}}]},"9":{"loc":{"start":{"line":76,"column":4},"end":{"line":76,"column":64}},"type":"if","locations":[{"start":{"line":76,"column":4},"end":{"line":76,"column":64}},{"start":{},"end":{}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":1},"f":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/services/likeService.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/services/likeService.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":64}},"1":{"start":{"line":4,"column":10},"end":{"line":4,"column":38}},"2":{"start":{"line":7,"column":20},"end":{"line":7,"column":58}},"3":{"start":{"line":8,"column":4},"end":{"line":8,"column":55}},"4":{"start":{"line":8,"column":18},"end":{"line":8,"column":55}},"5":{"start":{"line":10,"column":21},"end":{"line":10,"column":71}},"6":{"start":{"line":11,"column":4},"end":{"line":13,"column":5}},"7":{"start":{"line":12,"column":6},"end":{"line":12,"column":75}},"8":{"start":{"line":14,"column":4},"end":{"line":14,"column":58}},"9":{"start":{"line":18,"column":20},"end":{"line":18,"column":58}},"10":{"start":{"line":19,"column":4},"end":{"line":19,"column":55}},"11":{"start":{"line":19,"column":18},"end":{"line":19,"column":55}},"12":{"start":{"line":21,"column":21},"end":{"line":21,"column":71}},"13":{"start":{"line":22,"column":4},"end":{"line":24,"column":5}},"14":{"start":{"line":23,"column":6},"end":{"line":23,"column":75}},"15":{"start":{"line":25,"column":4},"end":{"line":25,"column":58}},"16":{"start":{"line":29,"column":4},"end":{"line":29,"column":47}},"17":{"start":{"line":33,"column":4},"end":{"line":33,"column":47}},"18":{"start":{"line":3,"column":0},"end":{"line":3,"column":13}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":3,"column":0},"end":{"line":3,"column":13}},"loc":{"start":{"line":3,"column":0},"end":{"line":35,"column":1}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":6,"column":2},"end":{"line":6,"column":7}},"loc":{"start":{"line":6,"column":53},"end":{"line":15,"column":3}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":17,"column":2},"end":{"line":17,"column":7}},"loc":{"start":{"line":17,"column":53},"end":{"line":26,"column":3}}},"3":{"name":"(anonymous_3)","decl":{"start":{"line":28,"column":2},"end":{"line":28,"column":7}},"loc":{"start":{"line":28,"column":39},"end":{"line":30,"column":3}}},"4":{"name":"(anonymous_4)","decl":{"start":{"line":32,"column":2},"end":{"line":32,"column":7}},"loc":{"start":{"line":32,"column":39},"end":{"line":34,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":8,"column":4},"end":{"line":8,"column":55}},"type":"if","locations":[{"start":{"line":8,"column":4},"end":{"line":8,"column":55}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":11,"column":4},"end":{"line":13,"column":5}},"type":"if","locations":[{"start":{"line":11,"column":4},"end":{"line":13,"column":5}},{"start":{},"end":{}}]},"2":{"loc":{"start":{"line":19,"column":4},"end":{"line":19,"column":55}},"type":"if","locations":[{"start":{"line":19,"column":4},"end":{"line":19,"column":55}},{"start":{},"end":{}}]},"3":{"loc":{"start":{"line":22,"column":4},"end":{"line":24,"column":5}},"type":"if","locations":[{"start":{"line":22,"column":4},"end":{"line":24,"column":5}},{"start":{},"end":{}}]}},"s":{"0":1,"1":1,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":1},"f":{"0":1,"1":0,"2":0,"3":0,"4":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/services/productService.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/services/productService.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":70}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":64}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":56}},"3":{"start":{"line":8,"column":10},"end":{"line":8,"column":41}},"4":{"start":{"line":9,"column":10},"end":{"line":9,"column":42}},"5":{"start":{"line":10,"column":10},"end":{"line":10,"column":44}},"6":{"start":{"line":13,"column":4},"end":{"line":13,"column":56}},"7":{"start":{"line":17,"column":44},"end":{"line":24,"column":10}},"8":{"start":{"line":25,"column":4},"end":{"line":25,"column":70}},"9":{"start":{"line":29,"column":4},"end":{"line":29,"column":34}},"10":{"start":{"line":37,"column":20},"end":{"line":37,"column":55}},"11":{"start":{"line":38,"column":4},"end":{"line":38,"column":47}},"12":{"start":{"line":38,"column":18},"end":{"line":38,"column":47}},"13":{"start":{"line":39,"column":4},"end":{"line":39,"column":64}},"14":{"start":{"line":39,"column":35},"end":{"line":39,"column":64}},"15":{"start":{"line":41,"column":21},"end":{"line":41,"column":34}},"16":{"start":{"line":42,"column":20},"end":{"line":42,"column":66}},"17":{"start":{"line":44,"column":4},"end":{"line":56,"column":5}},"18":{"start":{"line":45,"column":25},"end":{"line":45,"column":80}},"19":{"start":{"line":47,"column":26},"end":{"line":47,"column":67}},"20":{"start":{"line":47,"column":51},"end":{"line":47,"column":66}},"21":{"start":{"line":49,"column":6},"end":{"line":55,"column":7}},"22":{"start":{"line":50,"column":8},"end":{"line":54,"column":10}},"23":{"start":{"line":58,"column":4},"end":{"line":58,"column":19}},"24":{"start":{"line":62,"column":20},"end":{"line":62,"column":55}},"25":{"start":{"line":63,"column":4},"end":{"line":63,"column":47}},"26":{"start":{"line":63,"column":18},"end":{"line":63,"column":47}},"27":{"start":{"line":64,"column":4},"end":{"line":64,"column":64}},"28":{"start":{"line":64,"column":35},"end":{"line":64,"column":64}},"29":{"start":{"line":66,"column":4},"end":{"line":66,"column":45}},"30":{"start":{"line":7,"column":0},"end":{"line":7,"column":13}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":7,"column":0},"end":{"line":7,"column":13}},"loc":{"start":{"line":7,"column":0},"end":{"line":68,"column":1}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":12,"column":2},"end":{"line":12,"column":7}},"loc":{"start":{"line":12,"column":53},"end":{"line":14,"column":3}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":16,"column":2},"end":{"line":16,"column":7}},"loc":{"start":{"line":16,"column":57},"end":{"line":26,"column":3}}},"3":{"name":"(anonymous_3)","decl":{"start":{"line":28,"column":2},"end":{"line":28,"column":7}},"loc":{"start":{"line":28,"column":28},"end":{"line":30,"column":3}}},"4":{"name":"(anonymous_4)","decl":{"start":{"line":32,"column":2},"end":{"line":32,"column":7}},"loc":{"start":{"line":35,"column":80},"end":{"line":59,"column":3}}},"5":{"name":"(anonymous_5)","decl":{"start":{"line":47,"column":44},"end":{"line":47,"column":45}},"loc":{"start":{"line":47,"column":51},"end":{"line":47,"column":66}}},"6":{"name":"(anonymous_6)","decl":{"start":{"line":61,"column":2},"end":{"line":61,"column":7}},"loc":{"start":{"line":61,"column":48},"end":{"line":67,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":17,"column":44},"end":{"line":24,"column":10}},"type":"cond-expr","locations":[{"start":{"line":18,"column":8},"end":{"line":23,"column":null}},{"start":{"line":24,"column":8},"end":{"line":24,"column":10}}]},"1":{"loc":{"start":{"line":38,"column":4},"end":{"line":38,"column":47}},"type":"if","locations":[{"start":{"line":38,"column":4},"end":{"line":38,"column":47}},{"start":{},"end":{}}]},"2":{"loc":{"start":{"line":39,"column":4},"end":{"line":39,"column":64}},"type":"if","locations":[{"start":{"line":39,"column":4},"end":{"line":39,"column":64}},{"start":{},"end":{}}]},"3":{"loc":{"start":{"line":44,"column":4},"end":{"line":56,"column":5}},"type":"if","locations":[{"start":{"line":44,"column":4},"end":{"line":56,"column":5}},{"start":{},"end":{}}]},"4":{"loc":{"start":{"line":44,"column":8},"end":{"line":44,"column":59}},"type":"binary-expr","locations":[{"start":{"line":44,"column":8},"end":{"line":44,"column":32}},{"start":{"line":44,"column":36},"end":{"line":44,"column":59}}]},"5":{"loc":{"start":{"line":63,"column":4},"end":{"line":63,"column":47}},"type":"if","locations":[{"start":{"line":63,"column":4},"end":{"line":63,"column":47}},{"start":{},"end":{}}]},"6":{"loc":{"start":{"line":64,"column":4},"end":{"line":64,"column":64}},"type":"if","locations":[{"start":{"line":64,"column":4},"end":{"line":64,"column":64}},{"start":{},"end":{}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":0,"7":1,"8":1,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":1},"f":{"0":1,"1":0,"2":1,"3":0,"4":0,"5":0,"6":0},"b":{"0":[0,1],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/services/userService.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/services/userService.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":28}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":64}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":46}},"3":{"start":{"line":7,"column":10},"end":{"line":7,"column":42}},"4":{"start":{"line":10,"column":19},"end":{"line":10,"column":62}},"5":{"start":{"line":11,"column":4},"end":{"line":11,"column":48}},"6":{"start":{"line":11,"column":16},"end":{"line":11,"column":48}},"7":{"start":{"line":13,"column":17},"end":{"line":13,"column":41}},"8":{"start":{"line":14,"column":27},"end":{"line":14,"column":65}},"9":{"start":{"line":16,"column":4},"end":{"line":16,"column":78}},"10":{"start":{"line":17,"column":4},"end":{"line":17,"column":55}},"11":{"start":{"line":21,"column":4},"end":{"line":21,"column":42}},"12":{"start":{"line":25,"column":47},"end":{"line":25,"column":49}},"13":{"start":{"line":26,"column":4},"end":{"line":26,"column":49}},"14":{"start":{"line":26,"column":18},"end":{"line":26,"column":49}},"15":{"start":{"line":27,"column":4},"end":{"line":27,"column":40}},"16":{"start":{"line":27,"column":15},"end":{"line":27,"column":40}},"17":{"start":{"line":29,"column":4},"end":{"line":29,"column":73}},"18":{"start":{"line":29,"column":46},"end":{"line":29,"column":73}},"19":{"start":{"line":31,"column":4},"end":{"line":31,"column":56}},"20":{"start":{"line":35,"column":17},"end":{"line":35,"column":41}},"21":{"start":{"line":36,"column":27},"end":{"line":36,"column":65}},"22":{"start":{"line":37,"column":4},"end":{"line":37,"column":73}},"23":{"start":{"line":38,"column":4},"end":{"line":38,"column":56}},"24":{"start":{"line":42,"column":4},"end":{"line":42,"column":54}},"25":{"start":{"line":46,"column":4},"end":{"line":46,"column":34}},"26":{"start":{"line":6,"column":0},"end":{"line":6,"column":13}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":6,"column":0},"end":{"line":6,"column":13}},"loc":{"start":{"line":6,"column":0},"end":{"line":48,"column":1}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":9,"column":2},"end":{"line":9,"column":7}},"loc":{"start":{"line":9,"column":38},"end":{"line":18,"column":3}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":20,"column":2},"end":{"line":20,"column":7}},"loc":{"start":{"line":20,"column":33},"end":{"line":22,"column":3}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":24,"column":2},"end":{"line":24,"column":7}},"loc":{"start":{"line":24,"column":75},"end":{"line":32,"column":3}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":34,"column":2},"end":{"line":34,"column":7}},"loc":{"start":{"line":34,"column":60},"end":{"line":39,"column":3}}},"5":{"name":"(anonymous_6)","decl":{"start":{"line":41,"column":2},"end":{"line":41,"column":7}},"loc":{"start":{"line":41,"column":34},"end":{"line":43,"column":3}}},"6":{"name":"(anonymous_7)","decl":{"start":{"line":45,"column":2},"end":{"line":45,"column":20}},"loc":{"start":{"line":45,"column":35},"end":{"line":47,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":11,"column":4},"end":{"line":11,"column":48}},"type":"if","locations":[{"start":{"line":11,"column":4},"end":{"line":11,"column":48}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":26,"column":4},"end":{"line":26,"column":49}},"type":"if","locations":[{"start":{"line":26,"column":4},"end":{"line":26,"column":49}},{"start":{},"end":{}}]},"2":{"loc":{"start":{"line":27,"column":4},"end":{"line":27,"column":40}},"type":"if","locations":[{"start":{"line":27,"column":4},"end":{"line":27,"column":40}},{"start":{},"end":{}}]},"3":{"loc":{"start":{"line":29,"column":4},"end":{"line":29,"column":73}},"type":"if","locations":[{"start":{"line":29,"column":4},"end":{"line":29,"column":73}},{"start":{},"end":{}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":1},"f":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0]}} +,"/home/baturs/4-sprint-mission/mission 9/src/socket/io.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/socket/io.ts","statementMap":{"0":{"start":{"line":5,"column":0},"end":{"line":5,"column":16}},"1":{"start":{"line":15,"column":0},"end":{"line":15,"column":16}},"2":{"start":{"line":1,"column":0},"end":{"line":1,"column":35}},"3":{"start":{"line":3,"column":24},"end":{"line":3,"column":28}},"4":{"start":{"line":6,"column":2},"end":{"line":11,"column":5}},"5":{"start":{"line":12,"column":2},"end":{"line":12,"column":12}},"6":{"start":{"line":16,"column":2},"end":{"line":18,"column":3}},"7":{"start":{"line":17,"column":4},"end":{"line":17,"column":59}},"8":{"start":{"line":19,"column":2},"end":{"line":19,"column":12}}},"fnMap":{"0":{"name":"initIo","decl":{"start":{"line":5,"column":16},"end":{"line":5,"column":22}},"loc":{"start":{"line":5,"column":34},"end":{"line":13,"column":1}}},"1":{"name":"getIo","decl":{"start":{"line":15,"column":16},"end":{"line":15,"column":21}},"loc":{"start":{"line":15,"column":21},"end":{"line":20,"column":1}}}},"branchMap":{"0":{"loc":{"start":{"line":16,"column":2},"end":{"line":18,"column":3}},"type":"if","locations":[{"start":{"line":16,"column":2},"end":{"line":18,"column":3}},{"start":{},"end":{}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":0,"8":1},"f":{"0":1,"1":1},"b":{"0":[0,1]}} +,"/home/baturs/4-sprint-mission/mission 9/src/socket/socket.ts": {"path":"/home/baturs/4-sprint-mission/mission 9/src/socket/socket.ts","statementMap":{"0":{"start":{"line":4,"column":0},"end":{"line":4,"column":16}},"1":{"start":{"line":1,"column":0},"end":{"line":1,"column":29}},"2":{"start":{"line":2,"column":0},"end":{"line":2,"column":31}},"3":{"start":{"line":5,"column":13},"end":{"line":5,"column":20}},"4":{"start":{"line":7,"column":2},"end":{"line":22,"column":5}},"5":{"start":{"line":8,"column":4},"end":{"line":8,"column":48}},"6":{"start":{"line":10,"column":18},"end":{"line":10,"column":46}},"7":{"start":{"line":11,"column":4},"end":{"line":11,"column":43}},"8":{"start":{"line":11,"column":16},"end":{"line":11,"column":43}},"9":{"start":{"line":13,"column":4},"end":{"line":21,"column":5}},"10":{"start":{"line":14,"column":22},"end":{"line":14,"column":null}},"11":{"start":{"line":18,"column":6},"end":{"line":18,"column":40}},"12":{"start":{"line":20,"column":6},"end":{"line":20,"column":26}}},"fnMap":{"0":{"name":"registerSocket","decl":{"start":{"line":4,"column":16},"end":{"line":4,"column":30}},"loc":{"start":{"line":4,"column":30},"end":{"line":23,"column":1}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":7,"column":22},"end":{"line":7,"column":23}},"loc":{"start":{"line":7,"column":33},"end":{"line":22,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":11,"column":4},"end":{"line":11,"column":43}},"type":"if","locations":[{"start":{"line":11,"column":4},"end":{"line":11,"column":43}},{"start":{},"end":{}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0},"f":{"0":1,"1":0},"b":{"0":[0,0]}} +} diff --git a/mission 9/coverage/lcov-report/base.css b/mission 9/coverage/lcov-report/base.css new file mode 100644 index 000000000..f418035b4 --- /dev/null +++ b/mission 9/coverage/lcov-report/base.css @@ -0,0 +1,224 @@ +body, html { + margin:0; padding: 0; + height: 100%; +} +body { + font-family: Helvetica Neue, Helvetica, Arial; + font-size: 14px; + color:#333; +} +.small { font-size: 12px; } +*, *:after, *:before { + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + box-sizing:border-box; + } +h1 { font-size: 20px; margin: 0;} +h2 { font-size: 14px; } +pre { + font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; + margin: 0; + padding: 0; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} +a { color:#0074D9; text-decoration:none; } +a:hover { text-decoration:underline; } +.strong { font-weight: bold; } +.space-top1 { padding: 10px 0 0 0; } +.pad2y { padding: 20px 0; } +.pad1y { padding: 10px 0; } +.pad2x { padding: 0 20px; } +.pad2 { padding: 20px; } +.pad1 { padding: 10px; } +.space-left2 { padding-left:55px; } +.space-right2 { padding-right:20px; } +.center { text-align:center; } +.clearfix { display:block; } +.clearfix:after { + content:''; + display:block; + height:0; + clear:both; + visibility:hidden; + } +.fl { float: left; } +@media only screen and (max-width:640px) { + .col3 { width:100%; max-width:100%; } + .hide-mobile { display:none!important; } +} + +.quiet { + color: #7f7f7f; + color: rgba(0,0,0,0.5); +} +.quiet a { opacity: 0.7; } + +.fraction { + font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; + font-size: 10px; + color: #555; + background: #E8E8E8; + padding: 4px 5px; + border-radius: 3px; + vertical-align: middle; +} + +div.path a:link, div.path a:visited { color: #333; } +table.coverage { + border-collapse: collapse; + margin: 10px 0 0 0; + padding: 0; +} + +table.coverage td { + margin: 0; + padding: 0; + vertical-align: top; +} +table.coverage td.line-count { + text-align: right; + padding: 0 5px 0 20px; +} +table.coverage td.line-coverage { + text-align: right; + padding-right: 10px; + min-width:20px; +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 100%; +} +.missing-if-branch { + display: inline-block; + margin-right: 5px; + border-radius: 3px; + position: relative; + padding: 0 4px; + background: #333; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} +.coverage-summary { + border-collapse: collapse; + width: 100%; +} +.coverage-summary tr { border-bottom: 1px solid #bbb; } +.keyline-all { border: 1px solid #ddd; } +.coverage-summary td, .coverage-summary th { padding: 10px; } +.coverage-summary tbody { border: 1px solid #bbb; } +.coverage-summary td { border-right: 1px solid #bbb; } +.coverage-summary td:last-child { border-right: none; } +.coverage-summary th { + text-align: left; + font-weight: normal; + white-space: nowrap; +} +.coverage-summary th.file { border-right: none !important; } +.coverage-summary th.pct { } +.coverage-summary th.pic, +.coverage-summary th.abs, +.coverage-summary td.pct, +.coverage-summary td.abs { text-align: right; } +.coverage-summary td.file { white-space: nowrap; } +.coverage-summary td.pic { min-width: 120px !important; } +.coverage-summary tfoot td { } + +.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} +.status-line { height: 10px; } +/* yellow */ +.cbranch-no { background: yellow !important; color: #111; } +/* dark red */ +.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } +.low .chart { border:1px solid #C21F39 } +.highlighted, +.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ + background: #C21F39 !important; +} +/* medium red */ +.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } +/* light red */ +.low, .cline-no { background:#FCE1E5 } +/* light green */ +.high, .cline-yes { background:rgb(230,245,208) } +/* medium green */ +.cstat-yes { background:rgb(161,215,106) } +/* dark green */ +.status-line.high, .high .cover-fill { background:rgb(77,146,33) } +.high .chart { border:1px solid rgb(77,146,33) } +/* dark yellow (gold) */ +.status-line.medium, .medium .cover-fill { background: #f9cd0b; } +.medium .chart { border:1px solid #f9cd0b; } +/* light yellow */ +.medium { background: #fff4c2; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +span.cline-neutral { background: #eaeaea; } + +.coverage-summary td.empty { + opacity: .5; + padding-top: 4px; + padding-bottom: 4px; + line-height: 1; + color: #888; +} + +.cover-fill, .cover-empty { + display:inline-block; + height: 12px; +} +.chart { + line-height: 0; +} +.cover-empty { + background: white; +} +.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } + +.wrapper { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -48px; +} +.footer, .push { + height: 48px; +} diff --git a/mission 9/coverage/lcov-report/block-navigation.js b/mission 9/coverage/lcov-report/block-navigation.js new file mode 100644 index 000000000..530d1ed2b --- /dev/null +++ b/mission 9/coverage/lcov-report/block-navigation.js @@ -0,0 +1,87 @@ +/* eslint-disable */ +var jumpToCode = (function init() { + // Classes of code we would like to highlight in the file view + var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; + + // Elements to highlight in the file listing view + var fileListingElements = ['td.pct.low']; + + // We don't want to select elements that are direct descendants of another match + var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` + + // Selector that finds elements on the page to which we can jump + var selector = + fileListingElements.join(', ') + + ', ' + + notSelector + + missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` + + // The NodeList of matching elements + var missingCoverageElements = document.querySelectorAll(selector); + + var currentIndex; + + function toggleClass(index) { + missingCoverageElements + .item(currentIndex) + .classList.remove('highlighted'); + missingCoverageElements.item(index).classList.add('highlighted'); + } + + function makeCurrent(index) { + toggleClass(index); + currentIndex = index; + missingCoverageElements.item(index).scrollIntoView({ + behavior: 'smooth', + block: 'center', + inline: 'center' + }); + } + + function goToPrevious() { + var nextIndex = 0; + if (typeof currentIndex !== 'number' || currentIndex === 0) { + nextIndex = missingCoverageElements.length - 1; + } else if (missingCoverageElements.length > 1) { + nextIndex = currentIndex - 1; + } + + makeCurrent(nextIndex); + } + + function goToNext() { + var nextIndex = 0; + + if ( + typeof currentIndex === 'number' && + currentIndex < missingCoverageElements.length - 1 + ) { + nextIndex = currentIndex + 1; + } + + makeCurrent(nextIndex); + } + + return function jump(event) { + if ( + document.getElementById('fileSearch') === document.activeElement && + document.activeElement != null + ) { + // if we're currently focused on the search input, we don't want to navigate + return; + } + + switch (event.which) { + case 78: // n + case 74: // j + goToNext(); + break; + case 66: // b + case 75: // k + case 80: // p + goToPrevious(); + break; + } + }; +})(); +window.addEventListener('keydown', jumpToCode); diff --git a/mission 9/coverage/lcov-report/favicon.png b/mission 9/coverage/lcov-report/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..c1525b811a167671e9de1fa78aab9f5c0b61cef7 GIT binary patch literal 445 zcmV;u0Yd(XP))rP{nL}Ln%S7`m{0DjX9TLF* zFCb$4Oi7vyLOydb!7n&^ItCzb-%BoB`=x@N2jll2Nj`kauio%aw_@fe&*}LqlFT43 z8doAAe))z_%=P%v^@JHp3Hjhj^6*Kr_h|g_Gr?ZAa&y>wxHE99Gk>A)2MplWz2xdG zy8VD2J|Uf#EAw*bo5O*PO_}X2Tob{%bUoO2G~T`@%S6qPyc}VkhV}UifBuRk>%5v( z)x7B{I~z*k<7dv#5tC+m{km(D087J4O%+<<;K|qwefb6@GSX45wCK}Sn*> + + + + Code coverage report for All files + + + + + + + + + +
+
+

All files

+
+ +
+ 48.37% + Statements + 357/738 +
+ + +
+ 15% + Branches + 30/200 +
+ + +
+ 26.15% + Functions + 34/130 +
+ + +
+ 52.38% + Lines + 352/672 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
src +
+
100%27/27100%0/0100%1/1100%27/27
src/controllers +
+
18.11%50/2762.17%2/9211.76%4/3421.18%50/236
src/dtos +
+
88.23%15/1750%2/450%2/488.23%15/17
src/lib +
+
83.33%30/3650%4/840%2/582.35%28/34
src/lib/passport +
+
84.84%28/3366.66%4/675%3/484.84%28/33
src/middlewares +
+
33.33%3/90%0/40%0/133.33%3/9
src/repositories +
+
28.81%17/590%0/127.69%3/3930.35%17/56
src/routers +
+
100%92/92100%0/0100%0/0100%92/92
src/services +
+
45.69%69/15120.31%13/6440.54%15/3750.38%66/131
src/socket +
+
59.09%13/2225%1/475%3/461.9%13/21
tests/helpers +
+
81.25%13/1666.66%4/6100%1/181.25%13/16
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/prettify.css b/mission 9/coverage/lcov-report/prettify.css new file mode 100644 index 000000000..b317a7cda --- /dev/null +++ b/mission 9/coverage/lcov-report/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/mission 9/coverage/lcov-report/prettify.js b/mission 9/coverage/lcov-report/prettify.js new file mode 100644 index 000000000..b3225238f --- /dev/null +++ b/mission 9/coverage/lcov-report/prettify.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/mission 9/coverage/lcov-report/sort-arrow-sprite.png b/mission 9/coverage/lcov-report/sort-arrow-sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed68316eb3f65dec9063332d2f69bf3093bbfab GIT binary patch literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^>_9Bd!3HEZxJ@+%Qh}Z>jv*C{$p!i!8j}?a+@3A= zIAGwzjijN=FBi!|L1t?LM;Q;gkwn>2cAy-KV{dn nf0J1DIvEHQu*n~6U}x}qyky7vi4|9XhBJ7&`njxgN@xNA8m%nc literal 0 HcmV?d00001 diff --git a/mission 9/coverage/lcov-report/sorter.js b/mission 9/coverage/lcov-report/sorter.js new file mode 100644 index 000000000..4ed70ae5a --- /dev/null +++ b/mission 9/coverage/lcov-report/sorter.js @@ -0,0 +1,210 @@ +/* eslint-disable */ +var addSorting = (function() { + 'use strict'; + var cols, + currentSort = { + index: 0, + desc: false + }; + + // returns the summary table element + function getTable() { + return document.querySelector('.coverage-summary'); + } + // returns the thead element of the summary table + function getTableHeader() { + return getTable().querySelector('thead tr'); + } + // returns the tbody element of the summary table + function getTableBody() { + return getTable().querySelector('tbody'); + } + // returns the th element for nth column + function getNthColumn(n) { + return getTableHeader().querySelectorAll('th')[n]; + } + + function onFilterInput() { + const searchValue = document.getElementById('fileSearch').value; + const rows = document.getElementsByTagName('tbody')[0].children; + + // Try to create a RegExp from the searchValue. If it fails (invalid regex), + // it will be treated as a plain text search + let searchRegex; + try { + searchRegex = new RegExp(searchValue, 'i'); // 'i' for case-insensitive + } catch (error) { + searchRegex = null; + } + + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + let isMatch = false; + + if (searchRegex) { + // If a valid regex was created, use it for matching + isMatch = searchRegex.test(row.textContent); + } else { + // Otherwise, fall back to the original plain text search + isMatch = row.textContent + .toLowerCase() + .includes(searchValue.toLowerCase()); + } + + row.style.display = isMatch ? '' : 'none'; + } + } + + // loads the search box + function addSearchBox() { + var template = document.getElementById('filterTemplate'); + var templateClone = template.content.cloneNode(true); + templateClone.getElementById('fileSearch').oninput = onFilterInput; + template.parentElement.appendChild(templateClone); + } + + // loads all columns + function loadColumns() { + var colNodes = getTableHeader().querySelectorAll('th'), + colNode, + cols = [], + col, + i; + + for (i = 0; i < colNodes.length; i += 1) { + colNode = colNodes[i]; + col = { + key: colNode.getAttribute('data-col'), + sortable: !colNode.getAttribute('data-nosort'), + type: colNode.getAttribute('data-type') || 'string' + }; + cols.push(col); + if (col.sortable) { + col.defaultDescSort = col.type === 'number'; + colNode.innerHTML = + colNode.innerHTML + ''; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function(a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function(a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc + ? ' sorted-desc' + : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function() { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i = 0; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector('.sorter').parentElement; + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function() { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(); + addSearchBox(); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/mission 9/coverage/lcov-report/src/app.ts.html b/mission 9/coverage/lcov-report/src/app.ts.html new file mode 100644 index 000000000..36a9892b7 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/app.ts.html @@ -0,0 +1,205 @@ + + + + + + Code coverage report for src/app.ts + + + + + + + + + +
+
+

All files / src app.ts

+
+ +
+ 100% + Statements + 27/27 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 27/27 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +411x +1x +1x +1x +1x +1x +1x +1x +1x +1x +  +1x +  +1x +1x +1x +  +1x +  +  +  +  +1x +  +1x +1x +  +1x +1x +  +1x +  +1x +1x +  +1x +1x +  +  +1x +1x
import express from "express";
+import cookieParser from "cookie-parser";
+import router from "./routers/index";
+import { PORT } from "./lib/constants";
+import passport from "./lib/passport/index";
+import cors from "cors";
+import { errorHandler } from "./middlewares/errorHandler";
+import http from "http";
+import { initIo } from "./socket/io"; // ⬅ io 초기화 함수만 import
+import { registerSocket } from "./socket/socket"; // ⬅ 소켓 이벤트 등록
+ 
+const app = express();
+ 
+app.use(express.urlencoded({ extended: true }));
+app.use(express.json());
+app.use(cookieParser());
+ 
+const corsOptions = {
+  origin: "http://localhost:3000",
+  optionsSuccessStatus: 200,
+  credentials: true,
+};
+app.use(cors(corsOptions));
+ 
+app.use(passport.initialize());
+app.use(router);
+ 
+app.use("/download", express.static("uploads"));
+app.use(errorHandler);
+ 
+const server = http.createServer(app);
+ 
+initIo(server);
+registerSocket();
+ 
+server.listen(PORT, () => {
+  console.log(`Server is running on http://localhost:${PORT}`);
+});
+ 
+export { app };     
+export default app;    
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/controllers/alertController.ts.html b/mission 9/coverage/lcov-report/src/controllers/alertController.ts.html new file mode 100644 index 000000000..2fc4584b3 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/controllers/alertController.ts.html @@ -0,0 +1,193 @@ + + + + + + Code coverage report for src/controllers/alertController.ts + + + + + + + + + +
+
+

All files / src/controllers alertController.ts

+
+ +
+ 28.57% + Statements + 6/21 +
+ + +
+ 0% + Branches + 0/8 +
+ + +
+ 33.33% + Functions + 1/3 +
+ + +
+ 28.57% + Lines + 6/21 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37  +1x +1x +  +1x +1x +  +1x +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { Request, Response } from "express";
+import { AlertService } from "../services/alertService";
+import status from "http-status";
+ 
+export class AlertController {
+  private service = new AlertService();
+ 
+  list = async (req: Request, res: Response) => {
+    if (!req.user)
+      return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+    const userId = req.user.id;
+    const alerts = await this.service.list(userId);
+    res.json(alerts);
+  };
+ 
+  markAsRead = async (req: Request, res: Response) => {
+    if (!req.user)
+      return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+ 
+    const userId = req.user.id;
+    const alertId = Number(req.params.id);
+ 
+    if (!alertId) {
+      throw new Error("Article not found");
+    }
+ 
+    const success = await this.service.read(alertId, userId);
+ 
+    if (!success) {
+      return res.status(status.FORBIDDEN).json({
+        message: "You do not have permission to read this alert",
+      });
+    }
+    res.status(204).send();
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/controllers/articleController.ts.html b/mission 9/coverage/lcov-report/src/controllers/articleController.ts.html new file mode 100644 index 000000000..53da414a1 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/controllers/articleController.ts.html @@ -0,0 +1,295 @@ + + + + + + Code coverage report for src/controllers/articleController.ts + + + + + + + + + +
+
+

All files / src/controllers articleController.ts

+
+ +
+ 10.63% + Statements + 5/47 +
+ + +
+ 0% + Branches + 0/16 +
+ + +
+ 0% + Functions + 0/5 +
+ + +
+ 12.82% + Lines + 5/39 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71  +1x +1x +1x +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { Request, Response, NextFunction } from "express";
+import status from "http-status";
+import { ArticleService } from "../services/articleService";
+import { ArticleCreateSchema, ArticleUpdateSchema, ArticleQuerySchema } from "../dtos/article.dto";
+ 
+const articleService = new ArticleService();
+ 
+export class ArticleController {
+  async create(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+ 
+      const parsed = ArticleCreateSchema.parse(req.body);
+      const article = await articleService.create(req.user.id, parsed);
+      res.status(status.CREATED).json(article);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async list(req: Request, res: Response, next: NextFunction) {
+    try {
+      const parsed = ArticleQuerySchema.parse(req.query);
+      const articles = await articleService.list(parsed);
+      res.status(status.OK).json(articles);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async detail(req: Request, res: Response, next: NextFunction) {
+    try {
+      const articleId = Number(req.params.id);
+      const article = await articleService.getDetail(articleId);
+      if (!article) return res.status(status.NOT_FOUND).json({ message: "Article not found" });
+      res.status(status.OK).json(article);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async update(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const parsed = ArticleUpdateSchema.parse(req.body) as { title?: string; content?: string; };
+      const articleId = Number(req.params.id);
+      const updated = await articleService.update(req.user.id, parsed, articleId);
+ 
+      res.status(status.OK).json(updated);
+    } catch (err: any) {
+      if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" });
+      if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" });
+      next(err);
+    }
+  }
+ 
+  async delete(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+ 
+      const articleId = Number(req.params.id);
+      await articleService.delete(req.user.id, articleId);
+      res.status(status.NO_CONTENT).end();
+    } catch (err: any) {
+      if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" });
+      if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" });
+      next(err);
+    }
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/controllers/commentController.ts.html b/mission 9/coverage/lcov-report/src/controllers/commentController.ts.html new file mode 100644 index 000000000..41496a876 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/controllers/commentController.ts.html @@ -0,0 +1,346 @@ + + + + + + Code coverage report for src/controllers/commentController.ts + + + + + + + + + +
+
+

All files / src/controllers commentController.ts

+
+ +
+ 12.5% + Statements + 7/56 +
+ + +
+ 0% + Branches + 0/16 +
+ + +
+ 0% + Functions + 0/6 +
+ + +
+ 14.58% + Lines + 7/48 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88  +1x +1x +1x +  +1x +  +1x +  +  +  +1x +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import status from "http-status";
+import { CommentService } from "../services/commentService";
+ 
+const commentService = new CommentService();
+ 
+const commentSchema = z.object({
+  content: z.string().min(5).max(100),
+});
+ 
+const commentListSchema = z.object({
+  id: z.coerce.number().int().positive(),
+  lastId: z.coerce.number().int().positive().optional(),
+});
+ 
+export class CommentController {
+  async createProductComment(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const productId = Number(req.params.id);
+      const parsed = commentSchema.parse(req.body);
+      const comment = await commentService.createProductComment(req.user.id, productId, parsed.content);
+      res.status(status.CREATED).json(comment);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async createArticleComment(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const articleId = Number(req.params.id);
+      const parsed = commentSchema.parse(req.body);
+      const comment = await commentService.createArticleComment(req.user.id, articleId, parsed.content);
+      res.status(status.CREATED).json(comment);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async modifyComment(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const commentId = Number(req.params.id);
+      const parsed = commentSchema.parse(req.body);
+      const updated = await commentService.updateComment(req.user.id, commentId, parsed.content);
+      res.status(status.OK).json(updated);
+    } catch (err: any) {
+      if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Comment not found" });
+      if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" });
+      next(err);
+    }
+  }
+ 
+  async deleteComment(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const commentId = Number(req.params.id);
+      await commentService.deleteComment(req.user.id, commentId);
+      res.status(status.NO_CONTENT).end();
+    } catch (err: any) {
+      if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Comment not found" });
+      if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" });
+      next(err);
+    }
+  }
+ 
+  async productCommentList(req: Request, res: Response, next: NextFunction) {
+    try {
+      const parsed = commentListSchema.parse({ id: req.params.id, lastId: req.query.lastId });
+      const comments = await commentService.getProductComments(parsed.id, parsed.lastId);
+      res.status(status.OK).json(comments);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async articleCommentList(req: Request, res: Response, next: NextFunction) {
+    try {
+      const parsed = commentListSchema.parse({ id: req.params.id, lastId: req.query.lastId });
+      const comments = await commentService.getArticleComments(parsed.id, parsed.lastId);
+      res.status(status.OK).json(comments);
+    } catch (err) {
+      next(err);
+    }
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/controllers/index.html b/mission 9/coverage/lcov-report/src/controllers/index.html new file mode 100644 index 000000000..510e41c53 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/controllers/index.html @@ -0,0 +1,206 @@ + + + + + + Code coverage report for src/controllers + + + + + + + + + +
+
+

All files src/controllers

+
+ +
+ 18.11% + Statements + 50/276 +
+ + +
+ 2.17% + Branches + 2/92 +
+ + +
+ 11.76% + Functions + 4/34 +
+ + +
+ 21.18% + Lines + 50/236 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
alertController.ts +
+
28.57%6/210%0/833.33%1/328.57%6/21
articleController.ts +
+
10.63%5/470%0/160%0/512.82%5/39
commentController.ts +
+
12.5%7/560%0/160%0/614.58%7/48
likeController.ts +
+
11.11%4/360%0/120%0/614.28%4/28
photoController.ts +
+
25%3/120%0/40%0/127.27%3/11
productController.ts +
+
29.78%14/476.25%1/1640%2/535.89%14/39
userController.ts +
+
19.29%11/575%1/2012.5%1/822%11/50
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/controllers/likeController.ts.html b/mission 9/coverage/lcov-report/src/controllers/likeController.ts.html new file mode 100644 index 000000000..56cd592e3 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/controllers/likeController.ts.html @@ -0,0 +1,235 @@ + + + + + + Code coverage report for src/controllers/likeController.ts + + + + + + + + + +
+
+

All files / src/controllers likeController.ts

+
+ +
+ 11.11% + Statements + 4/36 +
+ + +
+ 0% + Branches + 0/12 +
+ + +
+ 0% + Functions + 0/6 +
+ + +
+ 14.28% + Lines + 4/28 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51  +1x +1x +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { Request, Response, NextFunction } from "express";
+import status from "http-status";
+import { LikeService } from "../services/likeService";
+ 
+const likeService = new LikeService();
+ 
+export class LikeController {
+  async likeArticle(req: Request, res: Response, next: NextFunction) {
+    if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+    try {
+      const result = await likeService.likeArticle(req.user.id, Number(req.params.id));
+      res.status(status.OK).json({ message: "Like toggled", isLiked: result.like });
+    } catch (err: any) {
+      if (err.message === "ARTICLE_NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" });
+      next(err);
+    }
+  }
+ 
+  async likeProduct(req: Request, res: Response, next: NextFunction) {
+    if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+    try {
+      const result = await likeService.likeProduct(req.user.id, Number(req.params.id));
+      res.status(status.OK).json({ message: "Like toggled", isLiked: result.like });
+    } catch (err: any) {
+      if (err.message === "PRODUCT_NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" });
+      next(err);
+    }
+  }
+ 
+  async getLikedArticles(req: Request, res: Response, next: NextFunction) {
+    if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+    try {
+      const likedArticles = await likeService.getLikedArticles(req.user.id);
+      const articles = likedArticles.map((l) => ({ ...l.article, isLiked: true }));
+      res.status(status.OK).json(articles);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async getLikedProducts(req: Request, res: Response, next: NextFunction) {
+    if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+    try {
+      const likedProducts = await likeService.getLikedProducts(req.user.id);
+      const products = likedProducts.map((l) => ({ ...l.product, isLiked: true }));
+      res.status(status.OK).json(products);
+    } catch (err) {
+      next(err);
+    }
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/controllers/photoController.ts.html b/mission 9/coverage/lcov-report/src/controllers/photoController.ts.html new file mode 100644 index 000000000..fdce873d3 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/controllers/photoController.ts.html @@ -0,0 +1,169 @@ + + + + + + Code coverage report for src/controllers/photoController.ts + + + + + + + + + +
+
+

All files / src/controllers photoController.ts

+
+ +
+ 25% + Statements + 3/12 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 27.27% + Lines + 3/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29  +1x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { Request, Response, NextFunction } from "express";
+import prisma from "../lib/prisma";
+import status from "http-status";
+ 
+export class PhotoController {
+  async upload(req: Request, res: Response, next: NextFunction) {
+    if (!req.user) return res.status(401).json({ message: "Unauthorized" });
+ 
+    if (!req.file) {
+      return res.status(status.BAD_REQUEST).json({ message: "No file uploaded" });
+    }
+ 
+    try {
+      const imageUrl = `/download/${req.file.filename}`;
+ 
+      const updatedUser = await prisma.user.update({
+        where: { id: req.user.id },
+        data: { image: imageUrl },
+      });
+ 
+      res.status(status.OK).json({
+        message: "Photo uploaded successfully",
+        image: updatedUser.image,
+      });
+    } catch (err) {
+      next(err);
+    }
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/controllers/productController.ts.html b/mission 9/coverage/lcov-report/src/controllers/productController.ts.html new file mode 100644 index 000000000..2f2f9e825 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/controllers/productController.ts.html @@ -0,0 +1,286 @@ + + + + + + Code coverage report for src/controllers/productController.ts + + + + + + + + + +
+
+

All files / src/controllers productController.ts

+
+ +
+ 29.78% + Statements + 14/47 +
+ + +
+ 6.25% + Branches + 1/16 +
+ + +
+ 40% + Functions + 2/5 +
+ + +
+ 35.89% + Lines + 14/39 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68  +1x +1x +1x +  +1x +  +1x +  +1x +1x +1x +1x +1x +  +  +  +  +  +  +1x +1x +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { Request, Response, NextFunction } from "express";
+import status from "http-status";
+import { ProductService } from "../services/productService";
+import { ProductCreateSchema, ProductUpdateSchema, ProductQuerySchema } from "../dtos/product.dto";
+ 
+const productService = new ProductService();
+ 
+export class ProductController {
+  async create(req: Request, res: Response, next: NextFunction) {
+    try {
+      Iif (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const parsed = ProductCreateSchema.parse(req.body);
+      const product = await productService.create(req.user.id, parsed);
+      res.status(status.CREATED).json(product);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async list(req: Request, res: Response, next: NextFunction) {
+    try {
+      const parsed = ProductQuerySchema.parse(req.query);
+      const products = await productService.list(parsed);
+      res.status(status.OK).json(products);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async detail(req: Request, res: Response, next: NextFunction) {
+    try {
+      const productId = Number(req.params.id);
+      const product = await productService.getDetail(productId);
+      if (!product) return res.status(status.NOT_FOUND).json({ message: "Product not found" });
+      res.status(status.OK).json(product);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async update(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const parsed = ProductUpdateSchema.parse(req.body) as { name?: string; description?: string; price?: number; tags?: string; };
+      const productId = Number(req.params.id);
+      const updated = await productService.update(req.user.id, productId, parsed);
+      
+      res.status(status.OK).json(updated);
+    } catch (err: any) {
+      if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" });
+      if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" });
+      next(err);
+    }
+  }
+ 
+  async delete(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const productId = Number(req.params.id);
+      await productService.delete(req.user.id, productId);
+      res.status(status.NO_CONTENT).end();
+    } catch (err: any) {
+      if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" });
+      if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" });
+      next(err);
+    }
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/controllers/userController.ts.html b/mission 9/coverage/lcov-report/src/controllers/userController.ts.html new file mode 100644 index 000000000..81514439b --- /dev/null +++ b/mission 9/coverage/lcov-report/src/controllers/userController.ts.html @@ -0,0 +1,376 @@ + + + + + + Code coverage report for src/controllers/userController.ts + + + + + + + + + +
+
+

All files / src/controllers userController.ts

+
+ +
+ 19.29% + Statements + 11/57 +
+ + +
+ 5% + Branches + 1/20 +
+ + +
+ 12.5% + Functions + 1/8 +
+ + +
+ 22% + Lines + 11/50 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98  +1x +1x +1x +1x +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +1x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { Request, Response, NextFunction } from "express";
+import status from "http-status";
+import { UserService } from "../services/userService";
+import { setTokenCookies, clearTokenCookies } from "../lib/cookieUtil";
+import { UserRegisterSchema, UserUpdateSchema, UserPasswordSchema, UserLoginSchema } from "../dtos/user.dto";
+ 
+const userService = new UserService();
+ 
+export class UserController {
+  async register(req: Request, res: Response, next: NextFunction) {
+    try {
+      const parsed = UserRegisterSchema.parse(req.body);
+      const result = await userService.register(parsed);
+      res.status(status.CREATED).json(result);
+    } catch (err: any) {
+      if (err.message === "EMAIL_EXISTS") {
+        return res.status(status.CONFLICT).json({ message: "This ID already exists" });
+      }
+      next(err);
+    }
+  }
+ 
+  login(req: Request, res: Response, next: NextFunction) {
+    Iif (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+ 
+    try {
+      const { accessToken, refreshToken } = userService.generateUserTokens(req.user.id);
+      setTokenCookies(res, accessToken, refreshToken);
+      
+      res.status(status.OK).json({ accessToken, refreshToken });
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async profile(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const profile = await userService.getProfile(req.user.id);
+      res.status(status.OK).json(profile);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async modifyInformation(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+ 
+      const parsed = UserUpdateSchema.parse(req.body); // DTO 검증
+      const updatedUser = await userService.updateInformation(req.user.id, parsed.nickname, parsed.image);
+ 
+      res.status(status.OK).json({ message: "User information updated successfully", user: updatedUser });
+    } catch (err: any) {
+      if (err.message === "NO_DATA") return res.status(status.BAD_REQUEST).json({ message: "No update data provided" });
+      next(err);
+    }
+  }
+ 
+  async modifyPassword(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+ 
+      const parsed = UserPasswordSchema.parse(req.body); // DTO 검증
+      const result = await userService.updatePassword(req.user.id, parsed);
+ 
+      res.status(status.OK).json(result);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async products(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const products = await userService.getProducts(req.user.id);
+      if (!products || products.length === 0) {
+        return res.status(status.NOT_FOUND).json({ message: "No product" });
+      }
+      res.status(status.OK).json(products);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  refreshTokens(req: Request, res: Response) {
+    if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+    const { accessToken, refreshToken } = userService.generateUserTokens(req.user.id);
+    setTokenCookies(res, accessToken, refreshToken);
+    res.status(status.OK).send({ message: "Tokens refreshed" });
+  }
+ 
+  logout(req: Request, res: Response) {
+    clearTokenCookies(res);
+    res.status(status.OK).send({ message: "Logged out successfully" });
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/dtos/article.dto.ts.html b/mission 9/coverage/lcov-report/src/dtos/article.dto.ts.html new file mode 100644 index 000000000..a8a7e21ed --- /dev/null +++ b/mission 9/coverage/lcov-report/src/dtos/article.dto.ts.html @@ -0,0 +1,199 @@ + + + + + + Code coverage report for src/dtos/article.dto.ts + + + + + + + + + +
+
+

All files / src/dtos article.dto.ts

+
+ +
+ 66.66% + Statements + 4/6 +
+ + +
+ 0% + Branches + 0/2 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 66.66% + Lines + 4/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +391x +  +  +1x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { z } from "zod";
+ 
+// CREATE DTO
+export const ArticleCreateSchema = z.object({
+  title: z.string().min(1, { message: "제목을 입력해주세요" }),
+  content: z
+    .string()
+    .min(10, { message: "내용은 최소 10자 이상이어야 합니다." })
+    .max(200, { message: "내용은 최대 200자까지 가능합니다." }),
+});
+export type ArticleCreateDTO = z.infer<typeof ArticleCreateSchema>;
+ 
+// UPDATE DTO (PATCH)
+export const ArticleUpdateSchema = z.object({
+  title: z.string().min(1, { message: "제목을 입력해주세요" }).optional(),
+  content: z
+    .string()
+    .min(10, { message: "내용은 최소 10자 이상이어야 합니다." })
+    .max(200, { message: "내용은 최대 200자까지 가능합니다." })
+    .optional(),
+});
+export type ArticleUpdateDTO = z.infer<typeof ArticleUpdateSchema>;
+ 
+// QUERY DTO (GET /articles)
+export const ArticleQuerySchema = z.object({
+  page: z
+    .string()
+    .default("1")
+    .transform(Number)
+    .refine((val) => val > 0, { message: "page는 1 이상의 정수여야 합니다." }),
+  pageSize: z
+    .string()
+    .default("5")
+    .transform(Number)
+    .refine((val) => val > 0 && val <= 100, { message: "pageSize는 1~100 사이여야 합니다." }),
+  keyword: z.string().default(""),
+});
+export type ArticleQueryDTO = z.infer<typeof ArticleQuerySchema>;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/dtos/index.html b/mission 9/coverage/lcov-report/src/dtos/index.html new file mode 100644 index 000000000..1986fc3ca --- /dev/null +++ b/mission 9/coverage/lcov-report/src/dtos/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for src/dtos + + + + + + + + + +
+
+

All files src/dtos

+
+ +
+ 88.23% + Statements + 15/17 +
+ + +
+ 50% + Branches + 2/4 +
+ + +
+ 50% + Functions + 2/4 +
+ + +
+ 88.23% + Lines + 15/17 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
article.dto.ts +
+
66.66%4/60%0/20%0/266.66%4/6
product.dto.ts +
+
100%6/6100%2/2100%2/2100%6/6
user.dto.ts +
+
100%5/5100%0/0100%0/0100%5/5
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/dtos/product.dto.ts.html b/mission 9/coverage/lcov-report/src/dtos/product.dto.ts.html new file mode 100644 index 000000000..980ae26d2 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/dtos/product.dto.ts.html @@ -0,0 +1,166 @@ + + + + + + Code coverage report for src/dtos/product.dto.ts + + + + + + + + + +
+
+

All files / src/dtos product.dto.ts

+
+ +
+ 100% + Statements + 6/6 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 6/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +281x +  +  +  +1x +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +1x +1x +1x +  +  + 
import { z } from "zod";
+ 
+ 
+// CREATE DTO 
+export const ProductCreateSchema = z.object({
+  name: z.string().min(1, { message: "이름을 입력해주세요" }),
+  description: z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }),
+  price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }),
+  tags: z.string().default(""),
+});
+export type ProductCreateDTO = z.infer<typeof ProductCreateSchema>;
+ 
+// UPDATE DTO
+export const ProductUpdateSchema = z.object({
+  name: z.string().min(1, { message: "이름을 입력해주세요" }).optional(),
+  description: z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }).optional(),
+  price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }).optional(),
+  tags: z.string().default("").optional(),
+});
+export type ProductUpdateDTO = z.infer<typeof ProductUpdateSchema>;
+ 
+// QUERY DTO
+export const ProductQuerySchema = z.object({
+  page: z.string().default("1").transform(Number).refine((v) => v > 0),
+  pageSize: z.string().default("5").transform(Number).refine((v) => v > 0 && v <= 100),
+  keyword: z.string().default(""),
+});
+export type ProductQueryDTO = z.infer<typeof ProductQuerySchema>;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/dtos/user.dto.ts.html b/mission 9/coverage/lcov-report/src/dtos/user.dto.ts.html new file mode 100644 index 000000000..cecc231e8 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/dtos/user.dto.ts.html @@ -0,0 +1,172 @@ + + + + + + Code coverage report for src/dtos/user.dto.ts + + + + + + + + + +
+
+

All files / src/dtos user.dto.ts

+
+ +
+ 100% + Statements + 5/5 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 5/5 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +301x +  +  +1x +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +1x +  +  +  +  +  +  +1x +  +  +  + 
import { z } from "zod";
+ 
+// 회원가입
+export const UserRegisterSchema = z.object({
+  email: z.string().email({ message: "Invalid email" }),
+  nickname: z.string().min(2, { message: "Nickname too short" }),
+  password: z.string().min(6, { message: "Password too short" }),
+});
+export type UserRegisterDTO = z.infer<typeof UserRegisterSchema>;
+ 
+// 로그인
+export const UserLoginSchema = z.object({
+  email: z.string().email(),
+  password: z.string().min(6),
+});
+export type UserLoginDTO = z.infer<typeof UserLoginSchema>;
+ 
+// 정보 수정 (PATCH)
+export const UserUpdateSchema = z.object({
+  nickname: z.string().min(2).optional(),
+  image: z.string().url().optional(),
+});
+export type UserUpdateDTO = z.infer<typeof UserUpdateSchema>;
+ 
+// 비밀번호 수정
+export const UserPasswordSchema = z.object({
+  password: z.string().min(6, { message: "Password too short" }),
+});
+export type UserPasswordDTO = z.infer<typeof UserPasswordSchema>;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/index.html b/mission 9/coverage/lcov-report/src/index.html new file mode 100644 index 000000000..146946887 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src + + + + + + + + + +
+
+

All files src

+
+ +
+ 100% + Statements + 27/27 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 27/27 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
app.ts +
+
100%27/27100%0/0100%1/1100%27/27
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/lib/constants.ts.html b/mission 9/coverage/lcov-report/src/lib/constants.ts.html new file mode 100644 index 000000000..b940eeb4f --- /dev/null +++ b/mission 9/coverage/lcov-report/src/lib/constants.ts.html @@ -0,0 +1,148 @@ + + + + + + Code coverage report for src/lib/constants.ts + + + + + + + + + +
+
+

All files / src/lib constants.ts

+
+ +
+ 100% + Statements + 14/14 +
+ + +
+ 50% + Branches + 4/8 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 14/14 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +222x +  +2x +  +2x +2x +  +2x +  +2x +2x +2x +  +  +2x +2x +2x +2x +2x +2x +  + 
import dotenv from 'dotenv';
+ 
+dotenv.config();
+ 
+const NODE_ENV = process.env.NODE_ENV || 'development';
+const PORT = process.env.PORT || 3000;
+const JWT_ACCESS_TOKEN_SECRET =
+  process.env.JWT_ACCESS_TOKEN_SECRET || 'your_jwt_access_token_secret';
+const JWT_REFRESH_TOKEN_SECRET =
+  process.env.JWT_REFRESH_TOKEN_SECRET || 'your_jwt_refresh_token_secret';
+const ACCESS_TOKEN_COOKIE_NAME = 'access-token';
+const REFRESH_TOKEN_COOKIE_NAME = 'refresh-token';
+ 
+export {
+  NODE_ENV,
+  PORT,
+  JWT_ACCESS_TOKEN_SECRET,
+  JWT_REFRESH_TOKEN_SECRET,
+  ACCESS_TOKEN_COOKIE_NAME,
+  REFRESH_TOKEN_COOKIE_NAME,
+};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/lib/cookieUtil.ts.html b/mission 9/coverage/lcov-report/src/lib/cookieUtil.ts.html new file mode 100644 index 000000000..e8b402fa8 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/lib/cookieUtil.ts.html @@ -0,0 +1,151 @@ + + + + + + Code coverage report for src/lib/cookieUtil.ts + + + + + + + + + +
+
+

All files / src/lib cookieUtil.ts

+
+ +
+ 71.42% + Statements + 5/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 50% + Functions + 1/2 +
+ + +
+ 71.42% + Lines + 5/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23  +1x +  +1x +1x +  +  +  +  +  +1x +  +  +  +  +  +  +  +1x +  +  +  + 
import { Response } from "express";
+import { ACCESS_TOKEN_COOKIE_NAME, REFRESH_TOKEN_COOKIE_NAME, NODE_ENV } from "./constants";
+ 
+export function setTokenCookies(res: Response, accessToken: string, refreshToken: string) {
+  res.cookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, {
+    httpOnly: true,
+    secure: NODE_ENV === "production",
+    maxAge: 1 * 60 * 60 * 1000, // 1시간
+  });
+ 
+  res.cookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken, {
+    httpOnly: true,
+    secure: NODE_ENV === "production",
+    maxAge: 7 * 24 * 60 * 60 * 1000, // 7일
+    path: "/users/refresh",
+  });
+}
+ 
+export function clearTokenCookies(res: Response) {
+  res.clearCookie(ACCESS_TOKEN_COOKIE_NAME);
+  res.clearCookie(REFRESH_TOKEN_COOKIE_NAME);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/lib/index.html b/mission 9/coverage/lcov-report/src/lib/index.html new file mode 100644 index 000000000..9dc43aef5 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/lib/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for src/lib + + + + + + + + + +
+
+

All files src/lib

+
+ +
+ 83.33% + Statements + 30/36 +
+ + +
+ 50% + Branches + 4/8 +
+ + +
+ 40% + Functions + 2/5 +
+ + +
+ 82.35% + Lines + 28/34 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
constants.ts +
+
100%14/1450%4/8100%0/0100%14/14
cookieUtil.ts +
+
71.42%5/7100%0/050%1/271.42%5/7
prisma.ts +
+
100%3/3100%0/0100%0/0100%3/3
token.ts +
+
66.66%8/12100%0/033.33%1/360%6/10
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/lib/passport/index.html b/mission 9/coverage/lcov-report/src/lib/passport/index.html new file mode 100644 index 000000000..d66c531bd --- /dev/null +++ b/mission 9/coverage/lcov-report/src/lib/passport/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for src/lib/passport + + + + + + + + + +
+
+

All files src/lib/passport

+
+ +
+ 84.84% + Statements + 28/33 +
+ + +
+ 66.66% + Branches + 4/6 +
+ + +
+ 75% + Functions + 3/4 +
+ + +
+ 84.84% + Lines + 28/33 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
100%7/7100%0/0100%0/0100%7/7
jwtStrategy.ts +
+
84.61%11/13100%2/266.66%2/384.61%11/13
localStrategy.ts +
+
76.92%10/1350%2/4100%1/176.92%10/13
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/lib/passport/index.ts.html b/mission 9/coverage/lcov-report/src/lib/passport/index.ts.html new file mode 100644 index 000000000..67a5e8c2b --- /dev/null +++ b/mission 9/coverage/lcov-report/src/lib/passport/index.ts.html @@ -0,0 +1,112 @@ + + + + + + Code coverage report for src/lib/passport/index.ts + + + + + + + + + +
+
+

All files / src/lib/passport index.ts

+
+ +
+ 100% + Statements + 7/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 7/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +101x +1x +1x +  +1x +1x +1x +  +1x + 
import passport from 'passport';
+import { localStrategy } from './localStrategy';
+import { accessTokenStrategy, refreshTokenStrategy } from './jwtStrategy';
+ 
+passport.use('local', localStrategy);
+passport.use('access-token', accessTokenStrategy);
+passport.use('refresh-token', refreshTokenStrategy);
+ 
+export default passport;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/lib/passport/jwtStrategy.ts.html b/mission 9/coverage/lcov-report/src/lib/passport/jwtStrategy.ts.html new file mode 100644 index 000000000..b07a13e38 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/lib/passport/jwtStrategy.ts.html @@ -0,0 +1,241 @@ + + + + + + Code coverage report for src/lib/passport/jwtStrategy.ts + + + + + + + + + +
+
+

All files / src/lib/passport jwtStrategy.ts

+
+ +
+ 84.61% + Statements + 11/13 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 66.66% + Functions + 2/3 +
+ + +
+ 84.61% + Lines + 11/13 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +531x +1x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +  +  +  +  +1x +  +  +  +  +  +1x +1x +  +  +1x +  +  +  +  +  +1x +  +  +  +  +1x +  +  +  + 
import { Strategy as JwtStrategy, ExtractJwt } from 'passport-jwt';
+import prisma from '../prisma';
+import type { Request } from 'express';
+import type { VerifiedCallback } from 'passport-jwt';
+import {
+  ACCESS_TOKEN_COOKIE_NAME,
+  REFRESH_TOKEN_COOKIE_NAME,
+  JWT_ACCESS_TOKEN_SECRET,
+  JWT_REFRESH_TOKEN_SECRET,
+} from '../constants';
+ 
+interface JwtPayload {
+  sub: number;
+}
+ 
+// const accessTokenOptions = {
+//   jwtFromRequest: (req: Request) => req.cookies[ACCESS_TOKEN_COOKIE_NAME],
+//   secretOrKey: JWT_ACCESS_TOKEN_SECRET,
+// };
+ 
+const accessTokenOptions = {
+  jwtFromRequest: (req: Request) => {
+    return req.cookies[ACCESS_TOKEN_COOKIE_NAME] || ExtractJwt.fromAuthHeaderAsBearerToken()(req);
+  },
+  secretOrKey: JWT_ACCESS_TOKEN_SECRET,
+};
+ 
+const refreshTokenOptions = {
+  jwtFromRequest: (req: Request) => req.cookies[REFRESH_TOKEN_COOKIE_NAME],
+  secretOrKey: JWT_REFRESH_TOKEN_SECRET,
+};
+ 
+async function jwtVerify(payload: JwtPayload, done: VerifiedCallback) {
+  try {
+    const user = await prisma.user.findUnique({
+      where: { id: payload.sub },
+    });
+    done(null, user);
+  } catch (error) {
+    done(error, false);
+  }
+}
+ 
+export const accessTokenStrategy = new JwtStrategy(
+  accessTokenOptions,
+  jwtVerify
+);
+ 
+export const refreshTokenStrategy = new JwtStrategy(
+  refreshTokenOptions,
+  jwtVerify
+);
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/lib/passport/localStrategy.ts.html b/mission 9/coverage/lcov-report/src/lib/passport/localStrategy.ts.html new file mode 100644 index 000000000..635fe46a3 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/lib/passport/localStrategy.ts.html @@ -0,0 +1,166 @@ + + + + + + Code coverage report for src/lib/passport/localStrategy.ts + + + + + + + + + +
+
+

All files / src/lib/passport localStrategy.ts

+
+ +
+ 76.92% + Statements + 10/13 +
+ + +
+ 50% + Branches + 2/4 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 76.92% + Lines + 10/13 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +281x +1x +1x +  +1x +  +  +  +  +  +1x +1x +1x +  +  +  +1x +1x +  +  +  +1x +  +  +  +  +  + 
import { Strategy as LocalStrategy } from "passport-local";
+import bcrypt from "bcrypt";
+import prisma from "../prisma";
+ 
+export const localStrategy = new LocalStrategy(
+  {
+    usernameField: "email", // email을 localStrategy의 고정값 'username' 대신 쓰도록 지정
+    passwordField: "password",
+  },
+  async (email, password, done) => {
+    try {
+      const user = await prisma.user.findUnique({ where: { email } });
+      Iif (!user) {
+        return done(null, false, { message: "No user found" });
+      }
+ 
+      const isPasswordValid = await bcrypt.compare(password, user.password);
+      Iif (!isPasswordValid) {
+        return done(null, false, { message: "Invalid password" });
+      }
+ 
+      return done(null, user);
+    } catch (err) {
+      return done(err);
+    }
+  }
+);
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/lib/prisma.ts.html b/mission 9/coverage/lcov-report/src/lib/prisma.ts.html new file mode 100644 index 000000000..fbb760558 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/lib/prisma.ts.html @@ -0,0 +1,97 @@ + + + + + + Code coverage report for src/lib/prisma.ts + + + + + + + + + +
+
+

All files / src/lib prisma.ts

+
+ +
+ 100% + Statements + 3/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 3/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +56x +  +6x +  +6x
import { PrismaClient } from '@prisma/client';
+ 
+const prisma = new PrismaClient();
+ 
+export default prisma;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/lib/token.ts.html b/mission 9/coverage/lcov-report/src/lib/token.ts.html new file mode 100644 index 000000000..48203fe56 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/lib/token.ts.html @@ -0,0 +1,166 @@ + + + + + + Code coverage report for src/lib/token.ts + + + + + + + + + +
+
+

All files / src/lib token.ts

+
+ +
+ 66.66% + Statements + 8/12 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 33.33% + Functions + 1/3 +
+ + +
+ 60% + Lines + 6/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +282x +2x +  +  +  +  +  +1x +  +  +1x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +2x + 
 import jwt from 'jsonwebtoken';
+import {
+  JWT_ACCESS_TOKEN_SECRET,
+  JWT_REFRESH_TOKEN_SECRET,
+} from './constants';
+ 
+function generateTokens(userId: number) {
+  const accessToken = jwt.sign({ sub: userId }, JWT_ACCESS_TOKEN_SECRET, {
+    expiresIn: '1h',
+  });
+  const refreshToken = jwt.sign({ sub: userId }, JWT_REFRESH_TOKEN_SECRET, {
+    expiresIn: '1d',
+  });
+  return { accessToken, refreshToken };
+}
+ 
+function verifyAccessToken(token: string) {
+  const decoded = jwt.verify(token, JWT_ACCESS_TOKEN_SECRET);
+  return { userId: decoded.sub };
+}
+ 
+function verifyRefreshToken(token: string) {
+  const decoded = jwt.verify(token, JWT_REFRESH_TOKEN_SECRET);
+  return { userId: decoded.sub };
+}
+ 
+export { generateTokens, verifyAccessToken, verifyRefreshToken };
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/middlewares/errorHandler.ts.html b/mission 9/coverage/lcov-report/src/middlewares/errorHandler.ts.html new file mode 100644 index 000000000..c310a6a3e --- /dev/null +++ b/mission 9/coverage/lcov-report/src/middlewares/errorHandler.ts.html @@ -0,0 +1,151 @@ + + + + + + Code coverage report for src/middlewares/errorHandler.ts + + + + + + + + + +
+
+

All files / src/middlewares errorHandler.ts

+
+ +
+ 33.33% + Statements + 3/9 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 33.33% + Lines + 3/9 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +231x +1x +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { z } from "zod";
+import httpStatus from "http-status";
+import express , { type Request, type Response, type NextFunction } from "express";
+ 
+interface ExtendedError extends Error {
+  code?: string;
+}
+ 
+export function errorHandler(err: ExtendedError, req: Request, res: Response, next: NextFunction) {
+  if (err instanceof z.ZodError) {
+    return res.status(httpStatus.BAD_REQUEST).json({ error: err.issues });
+  }
+ 
+  if (err.code === "P2025") {
+    return res.status(httpStatus.NOT_FOUND).json({ error: "Record not found" });
+  }
+ 
+  console.error("unhandled Error:", err);
+  return res
+    .status(httpStatus.INTERNAL_SERVER_ERROR)
+    .json({ error: "Internal Server Error" });
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/middlewares/index.html b/mission 9/coverage/lcov-report/src/middlewares/index.html new file mode 100644 index 000000000..69f5184aa --- /dev/null +++ b/mission 9/coverage/lcov-report/src/middlewares/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/middlewares + + + + + + + + + +
+
+

All files src/middlewares

+
+ +
+ 33.33% + Statements + 3/9 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 33.33% + Lines + 3/9 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
errorHandler.ts +
+
33.33%3/90%0/40%0/133.33%3/9
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/repositories/alertRepository.ts.html b/mission 9/coverage/lcov-report/src/repositories/alertRepository.ts.html new file mode 100644 index 000000000..2697d7947 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/repositories/alertRepository.ts.html @@ -0,0 +1,184 @@ + + + + + + Code coverage report for src/repositories/alertRepository.ts + + + + + + + + + +
+
+

All files / src/repositories alertRepository.ts

+
+ +
+ 28.57% + Statements + 2/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/5 +
+ + +
+ 28.57% + Lines + 2/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +343x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import prisma from "../lib/prisma";
+ 
+export class AlertRepository {
+  async createAlert(data: { userId: number; message: string; link?: string }) {
+    return prisma.alert.create({ data });
+  }
+ 
+  async findByUserId(userId: number) {
+    return prisma.alert.findMany({
+      where: { userId },
+      orderBy: { createdAt: "desc" },
+    });
+  }
+ 
+  async markAsRead(id: number) {
+    return prisma.alert.update({
+      where: { id },
+      data: { isRead: true },
+    });
+  }
+ 
+  async countUnread(userId: number) {
+    return prisma.alert.count({
+      where: { userId, isRead: false },
+    });
+  }
+ 
+  async findById(id: number) {
+    return prisma.alert.findUnique({
+      where: { id },
+    });
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/repositories/articleRepository.ts.html b/mission 9/coverage/lcov-report/src/repositories/articleRepository.ts.html new file mode 100644 index 000000000..524268e2c --- /dev/null +++ b/mission 9/coverage/lcov-report/src/repositories/articleRepository.ts.html @@ -0,0 +1,199 @@ + + + + + + Code coverage report for src/repositories/articleRepository.ts + + + + + + + + + +
+
+

All files / src/repositories articleRepository.ts

+
+ +
+ 23.07% + Statements + 3/13 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 0% + Functions + 0/5 +
+ + +
+ 27.27% + Lines + 3/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +391x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x
import prisma from "../lib/prisma";
+import { Prisma } from "@prisma/client";
+ 
+export class ArticleRepository {
+  async createArticle(data: { userId: number; title: string; content: string }) {
+    return prisma.article.create({ data });
+  }
+ 
+  async findMany(where: Prisma.ArticleWhereInput, skip: number, take: number) {
+    return prisma.article.findMany({
+      skip,
+      take,
+      orderBy: { createdAt: "desc" },
+      select: { id: true, title: true, content: true, createdAt: true },
+      where,
+    });
+  }
+ 
+  async findById(id: number) {
+    return prisma.article.findUnique({
+      where: { id },
+      select: { id: true, userId: true, title: true, content: true, createdAt: true },
+    });
+  }
+ 
+  async updatedArticle(id: number, data: { title?: string; content?: string }) {
+    const updateData: { title?: string; content?: string } = {};
+    if (data.title !== undefined) updateData.title = data.title;
+    if (data.content !== undefined) updateData.content = data.content;
+ 
+    return prisma.article.update({ where: { id }, data: updateData });
+  }
+ 
+  async deleteArticle(id: number): Promise<void> {
+    await prisma.article.delete({ where: { id } });
+  }
+}
+ 
+export default new ArticleRepository();
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/repositories/commentRepository.ts.html b/mission 9/coverage/lcov-report/src/repositories/commentRepository.ts.html new file mode 100644 index 000000000..50f4a7a48 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/repositories/commentRepository.ts.html @@ -0,0 +1,238 @@ + + + + + + Code coverage report for src/repositories/commentRepository.ts + + + + + + + + + +
+
+

All files / src/repositories commentRepository.ts

+
+ +
+ 30% + Statements + 3/10 +
+ + +
+ 0% + Branches + 0/8 +
+ + +
+ 0% + Functions + 0/7 +
+ + +
+ 30% + Lines + 3/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +521x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x
import prisma from "../lib/prisma";
+ 
+export class CommentRepository {
+  async createProductComment(userId: number, productId: number, content: string) {
+    return prisma.comment.create({
+      data: { content, productId, articleId: null, userId },
+    });
+  }
+ 
+  async createArticleComment(userId: number, articleId: number, content: string) {
+    return prisma.comment.create({
+      data: { content, productId: null, articleId, userId },
+    });
+  }
+ 
+  async findById(commentId: number) {
+    return prisma.comment.findUnique({ where: { id: commentId } });
+  }
+ 
+  async updateComment(commentId: number, content: string) {
+    return prisma.comment.update({
+      where: { id: commentId },
+      data: { content },
+    });
+  }
+ 
+  async deleteComment(commentId: number) {
+    return prisma.comment.delete({ where: { id: commentId } });
+  }
+ 
+  async findProductComments(productId: number, lastId?: number) {
+    return prisma.comment.findMany({
+      where: { articleId: null, productId },
+      take: 5,
+      skip: lastId ? 1 : 0,
+      ...(lastId && { cursor: { id: lastId } }),
+      select: { id: true, content: true, createdAt: true },
+    });
+  }
+ 
+  async findArticleComments(articleId: number, lastId?: number) {
+    return prisma.comment.findMany({
+      where: { articleId, productId: null },
+      take: 5,
+      skip: lastId ? 1 : 0,
+      ...(lastId && { cursor: { id: lastId } }),
+      select: { id: true, content: true, createdAt: true },
+    });
+  }
+}
+ 
+export default new CommentRepository();
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/repositories/index.html b/mission 9/coverage/lcov-report/src/repositories/index.html new file mode 100644 index 000000000..897b2f94f --- /dev/null +++ b/mission 9/coverage/lcov-report/src/repositories/index.html @@ -0,0 +1,191 @@ + + + + + + Code coverage report for src/repositories + + + + + + + + + +
+
+

All files src/repositories

+
+ +
+ 28.81% + Statements + 17/59 +
+ + +
+ 0% + Branches + 0/12 +
+ + +
+ 7.69% + Functions + 3/39 +
+ + +
+ 30.35% + Lines + 17/56 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
alertRepository.ts +
+
28.57%2/7100%0/00%0/528.57%2/7
articleRepository.ts +
+
23.07%3/130%0/40%0/527.27%3/11
commentRepository.ts +
+
30%3/100%0/80%0/730%3/10
likeRepository.ts +
+
13.33%2/15100%0/00%0/1214.28%2/14
productRepository.ts +
+
57.14%4/7100%0/040%2/557.14%4/7
userRepository.ts +
+
42.85%3/7100%0/020%1/542.85%3/7
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/repositories/likeRepository.ts.html b/mission 9/coverage/lcov-report/src/repositories/likeRepository.ts.html new file mode 100644 index 000000000..b56aa814f --- /dev/null +++ b/mission 9/coverage/lcov-report/src/repositories/likeRepository.ts.html @@ -0,0 +1,340 @@ + + + + + + Code coverage report for src/repositories/likeRepository.ts + + + + + + + + + +
+
+

All files / src/repositories likeRepository.ts

+
+ +
+ 13.33% + Statements + 2/15 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/12 +
+ + +
+ 14.28% + Lines + 2/14 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +862x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import prisma from "../lib/prisma";
+ 
+export class LikeRepository {
+  async findArticle(articleId: number) {
+    return prisma.article.findUnique({ where: { id: articleId } });
+  }
+ 
+  async findProduct(productId: number) {
+    return prisma.product.findUnique({ where: { id: productId } });
+  }
+ 
+  async findArticleLike(userId: number, articleId: number) {
+    return prisma.like.findUnique({
+      where: { userId_articleId: { userId, articleId } },
+    });
+  }
+ 
+  async findProductLike(userId: number, productId: number) {
+    return prisma.like.findUnique({
+      where: { userId_productId: { userId, productId } },
+    });
+  }
+ 
+  async toggleArticleLike(userId: number, articleId: number, current: boolean) {
+    return prisma.like.update({
+      where: { userId_articleId: { userId, articleId } },
+      data: { like: !current },
+    });
+  }
+ 
+  async toggleProductLike(userId: number, productId: number, current: boolean) {
+    return prisma.like.update({
+      where: { userId_productId: { userId, productId } },
+      data: { like: !current },
+    });
+  }
+ 
+  async createArticleLike(userId: number, articleId: number) {
+    return prisma.like.create({
+      data: { like: true, userId, articleId },
+    });
+  }
+ 
+  async createProductLike(userId: number, productId: number) {
+    return prisma.like.create({
+      data: { like: true, userId, productId },
+    });
+  }
+ 
+  async findLikedArticles(userId: number) {
+    return prisma.like.findMany({
+      where: { userId, articleId: { not: null }, like: true },
+      include: {
+        article: { select: { id: true, title: true } },
+      },
+    });
+  }
+ 
+  async findLikedProducts(userId: number) {
+    return prisma.like.findMany({
+      where: { userId, productId: { not: null }, like: true },
+      include: {
+        product: { select: { id: true, name: true, price: true, tags: true } },
+      },
+    });
+  }
+ 
+  async findUsersWhoLikedProduct(productId: number) {
+    const likes = await prisma.like.findMany({
+      where: {
+        productId,
+        like: true,
+      },
+      select: {
+        user: {
+          select: {
+            id: true,
+            nickname: true,
+          },
+        },
+      },
+    });
+    return likes.map((like) => like.user);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/repositories/productRepository.ts.html b/mission 9/coverage/lcov-report/src/repositories/productRepository.ts.html new file mode 100644 index 000000000..0ddd0f311 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/repositories/productRepository.ts.html @@ -0,0 +1,229 @@ + + + + + + Code coverage report for src/repositories/productRepository.ts + + + + + + + + + +
+
+

All files / src/repositories productRepository.ts

+
+ +
+ 57.14% + Statements + 4/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 40% + Functions + 2/5 +
+ + +
+ 57.14% + Lines + 4/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +492x +  +  +  +2x +  +1x +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import prisma from "../lib/prisma";
+import { Prisma } from "@prisma/client";
+import { ProductCreateDTO, ProductUpdateDTO, ProductQueryDTO } from "../dtos/product.dto";
+ 
+export class ProductRepository {
+  async createProduct(data: { userId: number; name: string; description: string; price: number; tags: string }) {
+    return prisma.product.create({ data });
+  }
+ 
+  async findMany(where: Prisma.ProductWhereInput, skip: number, take: number) {
+    return prisma.product.findMany({
+      skip,
+      take,
+      orderBy: { createdAt: "desc" },
+      select: {
+        id: true,
+        name: true,
+        description: true,
+        price: true,
+        tags: true,
+        createdAt: true,
+      },
+      where,
+    });
+  }
+ 
+  async findById(id: number) {
+    return prisma.product.findUnique({
+      where: { id },
+      select: {
+        id: true,
+        userId: true,
+        name: true,
+        description: true,
+        price: true,
+        tags: true,
+        createdAt: true,
+      },
+    });
+  }
+ 
+  async updateProduct(id: number, data: Partial<{ name: string; description: string; price: number; tags: string }>) {
+    return prisma.product.update({ where: { id }, data });
+  }
+ 
+  async deleteProduct(id: number) {
+    return prisma.product.delete({ where: { id } });
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/repositories/userRepository.ts.html b/mission 9/coverage/lcov-report/src/repositories/userRepository.ts.html new file mode 100644 index 000000000..037b09000 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/repositories/userRepository.ts.html @@ -0,0 +1,169 @@ + + + + + + Code coverage report for src/repositories/userRepository.ts + + + + + + + + + +
+
+

All files / src/repositories userRepository.ts

+
+ +
+ 42.85% + Statements + 3/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 20% + Functions + 1/5 +
+ + +
+ 42.85% + Lines + 3/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +292x +  +2x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import prisma from "../lib/prisma";
+ 
+export class UserRepository {
+  async findByEmail(email: string) {
+    return prisma.user.findUnique({ where: { email } });
+  }
+ 
+  async findById(id: number) {
+    return prisma.user.findUnique({
+      where: { id },
+      select: { id: true, email: true, nickname: true, image: true, createdAt: true, updatedAt: true },
+    });
+  }
+ 
+  async createUser(email: string, nickname: string, password: string) {
+    return prisma.user.create({ data: { email, nickname, password } });
+  }
+ 
+  async updateUser(id: number, data: Partial<{ nickname: string; image: string; password: string }>) {
+    return prisma.user.update({ where: { id }, data });
+  }
+ 
+  async findProductsByUserId(userId: number) {
+    return prisma.product.findMany({
+      where: { userId },
+      select: { name: true, description: true, price: true, tags: true },
+    });
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/routers/alertRouter.ts.html b/mission 9/coverage/lcov-report/src/routers/alertRouter.ts.html new file mode 100644 index 000000000..3ec8fbfe6 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/routers/alertRouter.ts.html @@ -0,0 +1,121 @@ + + + + + + Code coverage report for src/routers/alertRouter.ts + + + + + + + + + +
+
+

All files / src/routers alertRouter.ts

+
+ +
+ 100% + Statements + 8/8 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 8/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +131x +1x +1x +  +1x +1x +  +1x +  +1x +  +1x + 
import express from "express";
+import passport from "../lib/passport";
+import { AlertController } from "../controllers/alertController";
+ 
+const router = express.Router();
+const controller = new AlertController();
+ 
+router.get("/", passport.authenticate("access-token", { session: false }), controller.list);
+ 
+router.patch("/:id/read", passport.authenticate("access-token", { session: false }), controller.markAsRead);
+ 
+export default router;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/routers/articleRouter.ts.html b/mission 9/coverage/lcov-report/src/routers/articleRouter.ts.html new file mode 100644 index 000000000..749abe064 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/routers/articleRouter.ts.html @@ -0,0 +1,130 @@ + + + + + + Code coverage report for src/routers/articleRouter.ts + + + + + + + + + +
+
+

All files / src/routers articleRouter.ts

+
+ +
+ 100% + Statements + 11/11 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 11/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +161x +1x +1x +  +1x +1x +  +1x +1x +1x +  +1x +1x +  +1x + 
import express from "express";
+import passport from "../lib/passport";
+import { ArticleController } from "../controllers/articleController";
+ 
+const router = express.Router();
+const controller = new ArticleController();
+ 
+router.post("/", passport.authenticate("access-token", { session: false }), controller.create);
+router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update);
+router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete);
+ 
+router.get("/", controller.list);
+router.get("/:id", controller.detail);
+ 
+export default router;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/routers/commentRouter.ts.html b/mission 9/coverage/lcov-report/src/routers/commentRouter.ts.html new file mode 100644 index 000000000..c745e95fe --- /dev/null +++ b/mission 9/coverage/lcov-report/src/routers/commentRouter.ts.html @@ -0,0 +1,139 @@ + + + + + + Code coverage report for src/routers/commentRouter.ts + + + + + + + + + +
+
+

All files / src/routers commentRouter.ts

+
+ +
+ 100% + Statements + 12/12 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 12/12 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +191x +1x +1x +  +1x +1x +  +  +1x +1x +1x +1x +  +  +1x +1x +  +1x + 
import express from "express";
+import passport from "../lib/passport";
+import { CommentController } from "../controllers/commentController";
+ 
+const router = express.Router();
+const controller = new CommentController();
+ 
+// Private
+router.post("/products/:id", passport.authenticate("access-token", { session: false }), controller.createProductComment);
+router.post("/articles/:id", passport.authenticate("access-token", { session: false }), controller.createArticleComment);
+router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.modifyComment);
+router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.deleteComment);
+ 
+// Public
+router.get("/products/:id", controller.productCommentList);
+router.get("/articles/:id", controller.articleCommentList);
+ 
+export default router;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/routers/index.html b/mission 9/coverage/lcov-report/src/routers/index.html new file mode 100644 index 000000000..81cbf91d1 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/routers/index.html @@ -0,0 +1,221 @@ + + + + + + Code coverage report for src/routers + + + + + + + + + +
+
+

All files src/routers

+
+ +
+ 100% + Statements + 92/92 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 92/92 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
alertRouter.ts +
+
100%8/8100%0/0100%0/0100%8/8
articleRouter.ts +
+
100%11/11100%0/0100%0/0100%11/11
commentRouter.ts +
+
100%12/12100%0/0100%0/0100%12/12
index.ts +
+
100%17/17100%0/0100%0/0100%17/17
likeRouter.ts +
+
100%10/10100%0/0100%0/0100%10/10
photoRouter.ts +
+
100%9/9100%0/0100%0/0100%9/9
productRouter.ts +
+
100%11/11100%0/0100%0/0100%11/11
userRouter.ts +
+
100%14/14100%0/0100%0/0100%14/14
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/routers/index.ts.html b/mission 9/coverage/lcov-report/src/routers/index.ts.html new file mode 100644 index 000000000..2f2bb7091 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/routers/index.ts.html @@ -0,0 +1,145 @@ + + + + + + Code coverage report for src/routers/index.ts + + + + + + + + + +
+
+

All files / src/routers index.ts

+
+ +
+ 100% + Statements + 17/17 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 17/17 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +211x +  +1x +1x +1x +1x +1x +1x +1x +  +1x +  +1x +1x +1x +1x +1x +1x +1x +  +1x
import express from "express";
+ 
+import userRouter from "./userRouter";
+import articleRouter from "./articleRouter";
+import productRouter from "./productRouter";
+import commentRouter from "./commentRouter";
+import likeRouter from "./likeRouter";
+import photoRouter from "./photoRouter";
+import alertRouter from "./alertRouter";
+ 
+const router = express.Router();
+ 
+router.use("/users", userRouter);
+router.use("/articles", articleRouter);
+router.use("/products", productRouter);
+router.use("/comments", commentRouter);
+router.use("/likes", likeRouter);
+router.use(photoRouter); 
+router.use("/alerts", alertRouter);
+ 
+export default router;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/routers/likeRouter.ts.html b/mission 9/coverage/lcov-report/src/routers/likeRouter.ts.html new file mode 100644 index 000000000..c62b30fe4 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/routers/likeRouter.ts.html @@ -0,0 +1,121 @@ + + + + + + Code coverage report for src/routers/likeRouter.ts + + + + + + + + + +
+
+

All files / src/routers likeRouter.ts

+
+ +
+ 100% + Statements + 10/10 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 10/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +131x +1x +1x +  +1x +1x +  +1x +1x +1x +1x +  +1x
import express from "express";
+import passport from "../lib/passport";
+import { LikeController } from "../controllers/likeController";
+ 
+const router = express.Router();
+const controller = new LikeController();
+ 
+router.post("/articles/:id", passport.authenticate("access-token", { session: false }), controller.likeArticle);
+router.post("/products/:id", passport.authenticate("access-token", { session: false }), controller.likeProduct);
+router.get("/articles", passport.authenticate("access-token", { session: false }), controller.getLikedArticles);
+router.get("/products", passport.authenticate("access-token", { session: false }), controller.getLikedProducts);
+ 
+export default router;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/routers/photoRouter.ts.html b/mission 9/coverage/lcov-report/src/routers/photoRouter.ts.html new file mode 100644 index 000000000..0dfcc18fc --- /dev/null +++ b/mission 9/coverage/lcov-report/src/routers/photoRouter.ts.html @@ -0,0 +1,136 @@ + + + + + + Code coverage report for src/routers/photoRouter.ts + + + + + + + + + +
+
+

All files / src/routers photoRouter.ts

+
+ +
+ 100% + Statements + 9/9 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 9/9 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +181x +1x +1x +1x +  +1x +1x +1x +  +1x +  +  +  +  +  +  +1x + 
import express from "express";
+import multer from "multer";
+import passport from "../lib/passport";
+import { PhotoController } from "../controllers/photoController";
+ 
+const router = express.Router();
+const upload = multer({ dest: "uploads/" });
+const controller = new PhotoController();
+ 
+router.post(
+  "/",
+  passport.authenticate("access-token", { session: false }),
+  upload.single("image"),
+  controller.upload
+);
+ 
+export default router;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/routers/productRouter.ts.html b/mission 9/coverage/lcov-report/src/routers/productRouter.ts.html new file mode 100644 index 000000000..f073f174a --- /dev/null +++ b/mission 9/coverage/lcov-report/src/routers/productRouter.ts.html @@ -0,0 +1,136 @@ + + + + + + Code coverage report for src/routers/productRouter.ts + + + + + + + + + +
+
+

All files / src/routers productRouter.ts

+
+ +
+ 100% + Statements + 11/11 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 11/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +181x +1x +1x +  +1x +1x +  +  +1x +1x +1x +  +  +1x +1x +  +1x + 
import express from "express";
+import passport from "../lib/passport";
+import { ProductController } from "../controllers/productController";
+ 
+const router = express.Router();
+const controller = new ProductController();
+ 
+// ✅ 인증 필요
+router.post("/", passport.authenticate("access-token", { session: false }), controller.create);
+router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update);
+router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete);
+ 
+// ✅ 인증 필요 X (공개)
+router.get("/", controller.list);
+router.get("/:id", controller.detail);
+ 
+export default router;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/routers/userRouter.ts.html b/mission 9/coverage/lcov-report/src/routers/userRouter.ts.html new file mode 100644 index 000000000..664184fa2 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/routers/userRouter.ts.html @@ -0,0 +1,136 @@ + + + + + + Code coverage report for src/routers/userRouter.ts + + + + + + + + + +
+
+

All files / src/routers userRouter.ts

+
+ +
+ 100% + Statements + 14/14 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 14/14 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +181x +1x +1x +  +1x +1x +  +1x +1x +1x +1x +1x +1x +1x +1x +  +1x + 
import express from "express";
+import passport from "../lib/passport";
+import { UserController } from "../controllers/userController";
+ 
+const router = express.Router();
+const controller = new UserController();
+ 
+router.post("/register", controller.register);
+router.post("/login", passport.authenticate("local", { session: false }), controller.login);
+router.get("/profile", passport.authenticate("access-token", { session: false }), controller.profile);
+router.patch("/modifyInformation", passport.authenticate("access-token", { session: false }), controller.modifyInformation);
+router.patch("/modifyPassword", passport.authenticate("access-token", { session: false }), controller.modifyPassword);
+router.get("/products", passport.authenticate("access-token", { session: false }), controller.products);
+router.post("/refresh", passport.authenticate("refresh-token", { session: false }), controller.refreshTokens);
+router.post("/logout", controller.logout);
+ 
+export default router;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/services/alertService.ts.html b/mission 9/coverage/lcov-report/src/services/alertService.ts.html new file mode 100644 index 000000000..d348e5c2a --- /dev/null +++ b/mission 9/coverage/lcov-report/src/services/alertService.ts.html @@ -0,0 +1,196 @@ + + + + + + Code coverage report for src/services/alertService.ts + + + + + + + + + +
+
+

All files / src/services alertService.ts

+
+ +
+ 82.35% + Statements + 14/17 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 60% + Functions + 3/5 +
+ + +
+ 87.5% + Lines + 14/16 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +383x +3x +  +3x +6x +  +  +1x +  +1x +1x +  +1x +  +  +  +  +  +  +  +2x +  +2x +  +2x +1x +  +  +1x +  +1x +  +  +  +  +  +  + 
import { AlertRepository } from "../repositories/alertRepository";
+import { getIo } from "../socket/io";
+ 
+export class AlertService {
+  private repo = new AlertRepository();
+ 
+  async create(userId: number, message: string, link?: string) {
+    const alert = await this.repo.createAlert({ userId, message, link });
+ 
+    const io = getIo();
+    io.to(`user:${userId}`).emit("newAlert", alert);
+ 
+    return alert;
+  }
+ 
+  async list(userId: number) {
+    return this.repo.findByUserId(userId);
+  }
+ 
+  async read(alertId: number, userId: number) {
+    const alert = await this.repo.findById(alertId);
+ 
+    Iif (!alert) return false;
+ 
+    if (alert.userId !== userId) {
+      return false;
+    }
+ 
+    await this.repo.markAsRead(alertId);
+ 
+    return true;
+  }
+ 
+  async countUnread(userId: number) {
+    return this.repo.countUnread(userId);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/services/articleService.ts.html b/mission 9/coverage/lcov-report/src/services/articleService.ts.html new file mode 100644 index 000000000..e2cbc4e58 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/services/articleService.ts.html @@ -0,0 +1,220 @@ + + + + + + Code coverage report for src/services/articleService.ts + + + + + + + + + +
+
+

All files / src/services articleService.ts

+
+ +
+ 20% + Statements + 4/20 +
+ + +
+ 0% + Branches + 0/10 +
+ + +
+ 16.66% + Functions + 1/6 +
+ + +
+ 25% + Lines + 4/16 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +461x +  +  +  +1x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x
import { ArticleRepository } from "../repositories/articleRepository";
+import type { ArticleCreateDTO, ArticleUpdateDTO, ArticleQueryDTO } from "../dtos/article.dto";
+import type { Prisma } from "@prisma/client";
+ 
+export class ArticleService {
+  private repo = new ArticleRepository();
+ 
+  async create(userId: number, data: ArticleCreateDTO) {
+    return this.repo.createArticle({ ...data, userId });
+  }
+ 
+  async list({ page, pageSize, keyword }: ArticleQueryDTO) {
+    const where: Prisma.ArticleWhereInput = keyword
+      ? {
+          OR: [
+            { title: { contains: keyword, mode: "insensitive" } },
+            { content: { contains: keyword, mode: "insensitive" } },
+          ],
+        }
+      : {};
+ 
+    return this.repo.findMany(where, (page - 1) * pageSize, pageSize);
+  }
+ 
+  async getDetail(id: number) {
+    return this.repo.findById(id);
+  }
+ 
+  async update(userId: number, data: ArticleUpdateDTO, articleId: number) {
+    const article = await this.repo.findById(articleId);
+    if (!article) throw new Error("NOT_FOUND");
+    if (article.userId !== userId) throw new Error("FORBIDDEN");
+ 
+    return this.repo.updatedArticle(articleId, data);
+  }
+ 
+  async delete(userId: number, articleId: number) {
+    const article = await this.repo.findById(articleId);
+    if (!article) throw new Error("NOT_FOUND");
+    if (article.userId !== userId) throw new Error("FORBIDDEN");
+ 
+    await this.repo.deleteArticle(articleId);
+  }
+}
+ 
+export default new ArticleService();
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/services/commentService.ts.html b/mission 9/coverage/lcov-report/src/services/commentService.ts.html new file mode 100644 index 000000000..e3a21ed08 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/services/commentService.ts.html @@ -0,0 +1,346 @@ + + + + + + Code coverage report for src/services/commentService.ts + + + + + + + + + +
+
+

All files / src/services commentService.ts

+
+ +
+ 24.32% + Statements + 9/37 +
+ + +
+ 0% + Branches + 0/20 +
+ + +
+ 14.28% + Functions + 1/7 +
+ + +
+ 27.27% + Lines + 9/33 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +881x +1x +1x +1x +  +1x +1x +1x +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { CommentRepository } from "../repositories/commentRepository";
+import { ArticleRepository } from "../repositories/articleRepository";
+import { ProductRepository } from "../repositories/productRepository";
+import { AlertService } from "../services/alertService";
+ 
+export class CommentService {
+  private repo = new CommentRepository();
+  private articleRepo = new ArticleRepository();
+  private productRepo = new ProductRepository();
+  private alertService = new AlertService();
+ 
+  async createArticleComment(
+    userId: number,
+    articleId: number,
+    content: string
+  ) {
+    const article = await this.articleRepo.findById(articleId);
+    if (!article) {
+      throw new Error("Article not found");
+    }
+ 
+    const comment = await this.repo.createArticleComment(
+      userId,
+      articleId,
+      content
+    );
+ 
+    if (article && article.userId !== userId) {
+      await this.alertService.create(
+        article.userId,
+        "내 게시글에 새로운 댓글이 달렸습니다.",
+        `/articles/${articleId}`
+      );
+    }
+ 
+    return comment;
+  }
+ 
+  async createProductComment(
+    userId: number,
+    productId: number,
+    content: string
+  ) {
+    const product = await this.productRepo.findById(productId);
+    if (!product) {
+      throw new Error("Product not found");
+    }
+ 
+    const comment = await this.repo.createProductComment(
+      userId,
+      productId,
+      content
+    );
+ 
+    if (product && product.userId !== userId) {
+      await this.alertService.create(
+        product.userId,
+        "내 판매글에 새로운 댓글이 달렸습니다.",
+        `/products/${productId}`
+      );
+    }
+ 
+    return comment;
+  }
+ 
+  async updateComment(userId: number, commentId: number, content: string) {
+    const comment = await this.repo.findById(commentId);
+    if (!comment) throw new Error("NOT_FOUND");
+    if (comment.userId !== userId) throw new Error("FORBIDDEN");
+    return this.repo.updateComment(commentId, content);
+  }
+ 
+  async deleteComment(userId: number, commentId: number) {
+    const comment = await this.repo.findById(commentId);
+    if (!comment) throw new Error("NOT_FOUND");
+    if (comment.userId !== userId) throw new Error("FORBIDDEN");
+    await this.repo.deleteComment(commentId);
+  }
+ 
+  async getProductComments(productId: number, lastId?: number) {
+    return this.repo.findProductComments(productId, lastId);
+  }
+ 
+  async getArticleComments(articleId: number, lastId?: number) {
+    return this.repo.findArticleComments(articleId, lastId);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/services/index.html b/mission 9/coverage/lcov-report/src/services/index.html new file mode 100644 index 000000000..024be5a5d --- /dev/null +++ b/mission 9/coverage/lcov-report/src/services/index.html @@ -0,0 +1,191 @@ + + + + + + Code coverage report for src/services + + + + + + + + + +
+
+

All files src/services

+
+ +
+ 45.69% + Statements + 69/151 +
+ + +
+ 20.31% + Branches + 13/64 +
+ + +
+ 40.54% + Functions + 15/37 +
+ + +
+ 50.38% + Lines + 66/131 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
alertService.ts +
+
82.35%14/1775%3/460%3/587.5%14/16
articleService.ts +
+
20%4/200%0/1016.66%1/625%4/16
commentService.ts +
+
24.32%9/370%0/2014.28%1/727.27%9/33
likeService.ts +
+
15.78%3/190%0/820%1/517.64%3/17
productService.ts +
+
83.87%26/3157.14%8/1485.71%6/792.3%24/26
userService.ts +
+
48.14%13/2725%2/842.85%3/752.17%12/23
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/services/likeService.ts.html b/mission 9/coverage/lcov-report/src/services/likeService.ts.html new file mode 100644 index 000000000..d5523177a --- /dev/null +++ b/mission 9/coverage/lcov-report/src/services/likeService.ts.html @@ -0,0 +1,187 @@ + + + + + + Code coverage report for src/services/likeService.ts + + + + + + + + + +
+
+

All files / src/services likeService.ts

+
+ +
+ 15.78% + Statements + 3/19 +
+ + +
+ 0% + Branches + 0/8 +
+ + +
+ 20% + Functions + 1/5 +
+ + +
+ 17.64% + Lines + 3/17 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +351x +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { LikeRepository } from "../repositories/likeRepository";
+ 
+export class LikeService {
+  private repo = new LikeRepository();
+ 
+  async likeArticle(userId: number, articleId: number) {
+    const article = await this.repo.findArticle(articleId);
+    if (!article) throw new Error("ARTICLE_NOT_FOUND");
+ 
+    const existing = await this.repo.findArticleLike(userId, articleId);
+    if (existing) {
+      return this.repo.toggleArticleLike(userId, articleId, existing.like);
+    }
+    return this.repo.createArticleLike(userId, articleId);
+  }
+ 
+  async likeProduct(userId: number, productId: number) {
+    const product = await this.repo.findProduct(productId);
+    if (!product) throw new Error("PRODUCT_NOT_FOUND");
+ 
+    const existing = await this.repo.findProductLike(userId, productId);
+    if (existing) {
+      return this.repo.toggleProductLike(userId, productId, existing.like);
+    }
+    return this.repo.createProductLike(userId, productId);
+  }
+ 
+  async getLikedArticles(userId: number) {
+    return this.repo.findLikedArticles(userId);
+  }
+ 
+  async getLikedProducts(userId: number) {
+    return this.repo.findLikedProducts(userId);
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/services/productService.ts.html b/mission 9/coverage/lcov-report/src/services/productService.ts.html new file mode 100644 index 000000000..ecccea01c --- /dev/null +++ b/mission 9/coverage/lcov-report/src/services/productService.ts.html @@ -0,0 +1,289 @@ + + + + + + Code coverage report for src/services/productService.ts + + + + + + + + + +
+
+

All files / src/services productService.ts

+
+ +
+ 83.87% + Statements + 26/31 +
+ + +
+ 57.14% + Branches + 8/14 +
+ + +
+ 85.71% + Functions + 6/7 +
+ + +
+ 92.3% + Lines + 24/26 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +692x +2x +2x +  +  +  +2x +4x +4x +4x +  +  +2x +  +  +  +1x +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +1x +1x +1x +  +1x +1x +  +1x +1x +  +1x +  +1x +1x +  +  +  +  +  +  +  +1x +  +  +  +1x +1x +1x +  +  +  +  + 
import { ProductRepository } from "../repositories/productRepository";
+import { LikeRepository } from "../repositories/likeRepository";
+import { AlertService } from "../services/alertService";
+import type { ProductCreateDTO, ProductQueryDTO } from "../dtos/product.dto";
+import type { Prisma } from "@prisma/client";
+ 
+export class ProductService {
+  private repo = new ProductRepository();
+  private likeRepo = new LikeRepository();
+  private alertService = new AlertService();
+ 
+  async create(userId: number, data: ProductCreateDTO) {
+    return this.repo.createProduct({ ...data, userId });
+  }
+ 
+  async list({ page, pageSize, keyword }: ProductQueryDTO) {
+    const where: Prisma.ProductWhereInput = keyword
+      ? {
+          OR: [
+            { name: { contains: keyword, mode: "insensitive" } },
+            { description: { contains: keyword, mode: "insensitive" } },
+          ],
+        }
+      : {};
+    return this.repo.findMany(where, (page - 1) * pageSize, pageSize);
+  }
+ 
+  async getDetail(id: number) {
+    return this.repo.findById(id);
+  }
+ 
+  async update(
+    userId: number,
+    productId: number,
+    data: { name?: string; description?: string; price?: number; tags?: string }
+  ) {
+    const product = await this.repo.findById(productId);
+    Iif (!product) throw new Error("NOT_FOUND");
+    Iif (product.userId !== userId) throw new Error("FORBIDDEN");
+ 
+    const oldPrice = product.price;
+    const updated = await this.repo.updateProduct(productId, data);
+ 
+    Eif (data.price !== undefined && data.price !== oldPrice) {
+      const likedUsers = await this.likeRepo.findUsersWhoLikedProduct(productId);
+      
+      const targetUsers = likedUsers.filter((u) => u.id !== userId);
+ 
+      for (const user of targetUsers) {
+        await this.alertService.create(
+          user.id,
+          `좋아요한 상품 "${updated.name}"의 가격이 ${oldPrice}원 → ${data.price}원으로 변경되었습니다.`,
+          `/products/${productId}`
+        );
+      }
+    }
+ 
+    return updated;
+  }
+ 
+  async delete(userId: number, productId: number) {
+    const product = await this.repo.findById(productId);
+    Iif (!product) throw new Error("NOT_FOUND");
+    Eif (product.userId !== userId) throw new Error("FORBIDDEN");
+ 
+    await this.repo.deleteProduct(productId);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/services/userService.ts.html b/mission 9/coverage/lcov-report/src/services/userService.ts.html new file mode 100644 index 000000000..449eb5e89 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/services/userService.ts.html @@ -0,0 +1,229 @@ + + + + + + Code coverage report for src/services/userService.ts + + + + + + + + + +
+
+

All files / src/services userService.ts

+
+ +
+ 48.14% + Statements + 13/27 +
+ + +
+ 25% + Branches + 2/8 +
+ + +
+ 42.85% + Functions + 3/7 +
+ + +
+ 52.17% + Lines + 12/23 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +492x +2x +2x +  +  +2x +4x +  +  +2x +2x +  +1x +1x +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  + 
import bcrypt from "bcrypt";
+import { UserRepository } from "../repositories/userRepository";
+import { generateTokens } from "../lib/token";
+import type { UserRegisterDTO, UserUpdateDTO, UserPasswordDTO } from "../dtos/user.dto";
+ 
+export class UserService {
+  private userRepo = new UserRepository();
+ 
+  async register(data: UserRegisterDTO) {
+    const exists = await this.userRepo.findByEmail(data.email);
+    if (exists) throw new Error("EMAIL_EXISTS");
+ 
+    const salt = await bcrypt.genSalt(10);
+    const hashedPassword = await bcrypt.hash(data.password, salt);
+ 
+    await this.userRepo.createUser(data.email, data.nickname, hashedPassword);
+    return { message: "User registered successfully" };
+  }
+ 
+  async getProfile(userId: number) {
+    return this.userRepo.findById(userId);
+  }
+ 
+  async updateInformation(userId: number, nickname?: string, image?: string) {
+    const updateData: Record<string, string> = {};
+    if (nickname) updateData.nickname = nickname;
+    if (image) updateData.image = image;
+ 
+    if (Object.keys(updateData).length === 0) throw new Error("NO_DATA");
+ 
+    return this.userRepo.updateUser(userId, updateData);
+  }
+ 
+  async updatePassword(userId: number, data: UserPasswordDTO) {
+    const salt = await bcrypt.genSalt(10);
+    const hashedPassword = await bcrypt.hash(data.password, salt);
+    await this.userRepo.updateUser(userId, { password: hashedPassword });
+    return { message: "Password updated successfully" };
+  }
+ 
+  async getProducts(userId: number) {
+    return this.userRepo.findProductsByUserId(userId);
+  }
+ 
+  generateUserTokens(userId: number) {
+    return generateTokens(userId);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/socket.ts.html b/mission 9/coverage/lcov-report/src/socket.ts.html new file mode 100644 index 000000000..93f1da548 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/socket.ts.html @@ -0,0 +1,130 @@ + + + + + + Code coverage report for src/socket.ts + + + + + + + + + +
+
+

All files / src socket.ts

+
+ +
+ 25% + Statements + 2/8 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 25% + Functions + 1/4 +
+ + +
+ 25% + Lines + 2/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16  +  +5x +5x +  +  +  +  +  +  +  +  +  +  +  + 
import { Server } from "socket.io";
+ 
+export function registerSocket(io: Server) {
+    io.on("connection", (socket) => {
+        console.log("New client connected:", socket.id);
+ 
+        socket.on("register", (userId: number) => {
+            socket.join(`user:${userId}`);
+            console.log(`User ${userId} joined room user:${userId}`);
+        });
+ 
+        socket.on("disconnect", () => {
+            console.log("Client disconnected:", socket.id);
+        });
+    });
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/socket/index.html b/mission 9/coverage/lcov-report/src/socket/index.html new file mode 100644 index 000000000..3efa2ab01 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/socket/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/socket + + + + + + + + + +
+
+

All files src/socket

+
+ +
+ 59.09% + Statements + 13/22 +
+ + +
+ 25% + Branches + 1/4 +
+ + +
+ 75% + Functions + 3/4 +
+ + +
+ 61.9% + Lines + 13/21 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
io.ts +
+
88.88%8/950%1/2100%2/288.88%8/9
socket.ts +
+
38.46%5/130%0/250%1/241.66%5/12
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/socket/io.ts.html b/mission 9/coverage/lcov-report/src/socket/io.ts.html new file mode 100644 index 000000000..c29d80438 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/socket/io.ts.html @@ -0,0 +1,145 @@ + + + + + + Code coverage report for src/socket/io.ts + + + + + + + + + +
+
+

All files / src/socket io.ts

+
+ +
+ 88.88% + Statements + 8/9 +
+ + +
+ 50% + Branches + 1/2 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 88.88% + Lines + 8/9 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +213x +  +3x +  +3x +1x +  +  +  +  +  +1x +  +  +3x +1x +  +  +1x +  + 
import { Server } from "socket.io";
+ 
+let io: Server | null = null;
+ 
+export function initIo(server: any) {
+  io = new Server(server, {
+    cors: {
+      origin: "http://localhost:3000",
+      methods: ["GET", "POST"],
+    },
+  });
+  return io;
+}
+ 
+export function getIo(): Server {
+  Iif (!io) {
+    throw new Error("Socket.io has not been initialized!");
+  }
+  return io;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/src/socket/socket.ts.html b/mission 9/coverage/lcov-report/src/socket/socket.ts.html new file mode 100644 index 000000000..de125c009 --- /dev/null +++ b/mission 9/coverage/lcov-report/src/socket/socket.ts.html @@ -0,0 +1,154 @@ + + + + + + Code coverage report for src/socket/socket.ts + + + + + + + + + +
+
+

All files / src/socket socket.ts

+
+ +
+ 38.46% + Statements + 5/13 +
+ + +
+ 0% + Branches + 0/2 +
+ + +
+ 50% + Functions + 1/2 +
+ + +
+ 41.66% + Lines + 5/12 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +241x +1x +  +1x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { getIo } from "./io";
+import jwt from "jsonwebtoken";
+ 
+export function registerSocket() {
+  const io = getIo(); // <-- initIo에서 만든 io 가져오기
+ 
+  io.on("connection", (socket) => {
+    console.log("Socket connected:", socket.id);
+ 
+    const token = socket.handshake.auth?.token;
+    if (!token) return socket.disconnect();
+ 
+    try {
+      const decoded = jwt.verify(token, process.env.JWT_SECRET!) as {
+        id: number;
+      };
+ 
+      socket.join(`user:${decoded.id}`);
+    } catch (err) {
+      socket.disconnect();
+    }
+  });
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/test/helpers/authHelper.ts.html b/mission 9/coverage/lcov-report/test/helpers/authHelper.ts.html new file mode 100644 index 000000000..c5cd6b345 --- /dev/null +++ b/mission 9/coverage/lcov-report/test/helpers/authHelper.ts.html @@ -0,0 +1,154 @@ + + + + + + Code coverage report for test/helpers/authHelper.ts + + + + + + + + + +
+
+

All files / test/helpers authHelper.ts

+
+ +
+ 100% + Statements + 7/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 7/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24  +4x +4x +  +4x +  +4x +  +  +  +  +4x +  +  +  +4x +  +4x +  +  +  +  +  + 
// ✅ test/helpers/authHelper.ts
+import supertest from "supertest";
+import app from "../../src/app";
+ 
+export const authHelper = {
+  async registerAndLogin() {
+    const userData = {
+      email: `test_${Date.now()}@test.com`,
+      password: "1234",
+      nickname: `nick_${Date.now()}`,
+    };
+    const registerRes = await supertest(app)
+      .post("/users/register")
+      .send(userData);
+ 
+    const loginRes = await supertest(app).post("/users/login").send(userData);
+ 
+    return {
+      token: loginRes.body.token,
+      user: loginRes.body.user, // <- 반드시 user 포함
+    };
+  },
+};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/test/helpers/index.html b/mission 9/coverage/lcov-report/test/helpers/index.html new file mode 100644 index 000000000..d98ac9d79 --- /dev/null +++ b/mission 9/coverage/lcov-report/test/helpers/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for test/helpers + + + + + + + + + +
+
+

All files test/helpers

+
+ +
+ 100% + Statements + 14/14 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 13/13 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
authHelper.ts +
+
100%7/7100%0/0100%1/1100%7/7
resetDatabase.ts +
+
100%7/7100%2/2100%1/1100%6/6
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/test/helpers/resetDatabase.ts.html b/mission 9/coverage/lcov-report/test/helpers/resetDatabase.ts.html new file mode 100644 index 000000000..e853802cc --- /dev/null +++ b/mission 9/coverage/lcov-report/test/helpers/resetDatabase.ts.html @@ -0,0 +1,124 @@ + + + + + + Code coverage report for test/helpers/resetDatabase.ts + + + + + + + + + +
+
+

All files / test/helpers resetDatabase.ts

+
+ +
+ 100% + Statements + 7/7 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 6/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +145x +  +5x +5x +  +  +  +5x +35x +30x +  +  +  + 
import prisma from "../../src/lib/prisma";
+ 
+export const resetDatabase = async () => {
+  const tablenames = await prisma.$queryRaw<
+    { tablename: string }[]
+  >`SELECT tablename FROM pg_tables WHERE schemaname='public'`;
+ 
+  for (const { tablename } of tablenames) {
+    if (tablename !== "_prisma_migrations") {
+      await prisma.$executeRawUnsafe(`TRUNCATE TABLE "${tablename}" RESTART IDENTITY CASCADE;`);
+    }
+  }
+};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/test/index.html b/mission 9/coverage/lcov-report/test/index.html new file mode 100644 index 000000000..d32cebf70 --- /dev/null +++ b/mission 9/coverage/lcov-report/test/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for test + + + + + + + + + +
+
+

All files test

+
+ +
+ 100% + Statements + 20/20 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 19/19 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
setup.ts +
+
100%9/9100%0/0100%1/1100%8/8
utils.ts +
+
100%11/11100%0/0100%1/1100%11/11
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/test/setup.ts.html b/mission 9/coverage/lcov-report/test/setup.ts.html new file mode 100644 index 000000000..770d8324b --- /dev/null +++ b/mission 9/coverage/lcov-report/test/setup.ts.html @@ -0,0 +1,118 @@ + + + + + + Code coverage report for test/setup.ts + + + + + + + + + +
+
+

All files / test setup.ts

+
+ +
+ 100% + Statements + 9/9 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 8/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +123x +  +  +3x +3x +3x +3x +3x +3x +3x +  + 
import prisma from "../src/lib/prisma";
+ 
+// 테스트 시작 전 DB 초기화
+export const clearDatabase = async () => {
+  await prisma.like.deleteMany();
+  await prisma.comment.deleteMany();
+  await prisma.article.deleteMany();
+  await prisma.product.deleteMany();
+  await prisma.alert.deleteMany();
+  await prisma.user.deleteMany();
+};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/test/utils.ts.html b/mission 9/coverage/lcov-report/test/utils.ts.html new file mode 100644 index 000000000..793ae1255 --- /dev/null +++ b/mission 9/coverage/lcov-report/test/utils.ts.html @@ -0,0 +1,181 @@ + + + + + + Code coverage report for test/utils.ts + + + + + + + + + +
+
+

All files / test utils.ts

+
+ +
+ 100% + Statements + 11/11 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 11/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +334x +4x +4x +  +4x +4x +4x +4x +  +  +4x +  +  +  +  +  +4x +  +  +  +  +4x +  +4x +  +  +  +  +  +  +  +  + 
import supertest from "supertest";
+import { app } from "../src/app";
+import { ACCESS_TOKEN_COOKIE_NAME } from "../src/lib/constants";
+ 
+export async function createTestUserAndGetToken() {
+  const email = `test${Date.now()}@test.com`;
+  const password = "password123";
+  const nickname = "테스트닉";
+ 
+  // 회원가입
+  await supertest(app)
+    .post("/users/register")
+    .send({ email, password, nickname })
+    .expect(201);
+ 
+  // 로그인
+  const loginRes = await supertest(app)
+    .post("/users/login")
+    .send({ email, password })
+    .expect(200);
+ 
+  const token = loginRes.body.token;
+ 
+  return {
+    email,
+    password,
+    nickname,
+    token,
+    authHeader: `Bearer ${token}`, // 테스트용 Authorization 헤더
+    cookieHeader: `${ACCESS_TOKEN_COOKIE_NAME}=${token}`, // 필요 시 쿠키용
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/tests/helpers/auth.ts.html b/mission 9/coverage/lcov-report/tests/helpers/auth.ts.html new file mode 100644 index 000000000..6422ee491 --- /dev/null +++ b/mission 9/coverage/lcov-report/tests/helpers/auth.ts.html @@ -0,0 +1,211 @@ + + + + + + Code coverage report for tests/helpers/auth.ts + + + + + + + + + +
+
+

All files / tests/helpers auth.ts

+
+ +
+ 81.25% + Statements + 13/16 +
+ + +
+ 66.66% + Branches + 4/6 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 81.25% + Lines + 13/16 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43  +1x +1x +1x +1x +  +  +  +  +  +  +1x +  +  +  +1x +  +  +1x +  +  +1x +  +  +  +  +  +1x +  +  +  +  +1x +  +  +1x +1x +  +  +  +1x +  + 
// tests/helpers/auth.ts
+import request from "supertest";
+import { app } from "../../src/app";
+import bcrypt from "bcrypt";
+import { UserRepository } from "../../src/repositories/userRepository";
+ 
+interface TokenResponse {
+  accessToken: string;
+  refreshToken?: string;
+}
+ 
+export async function loginAndGetToken(
+  email = "test@test.com",
+  password = "123456"
+): Promise<TokenResponse> {
+  const userRepo = new UserRepository();
+ 
+  // 1️⃣ 테스트용 유저 확인
+  let existing = await userRepo.findByEmail(email);
+ 
+  // 2️⃣ 없으면 생성
+  Iif (!existing) {
+    const hashed = await bcrypt.hash(password, 10);
+    existing = await userRepo.createUser(email, "tester", hashed);
+  }
+ 
+  // 3️⃣ 로그인 요청
+  const res = await request(app)
+    .post("/users/login")
+    .send({ email, password })
+    .expect(200);
+ 
+  console.log("Login response body:", res.body); // 디버깅용
+ 
+  // 4️⃣ 로그인 성공 시 accessToken 반환
+  const { accessToken, refreshToken } = res.body;
+  Iif (!accessToken) {
+    throw new Error("로그인 실패: accessToken이 반환되지 않았습니다.");
+  }
+ 
+  return { accessToken, refreshToken };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/tests/helpers/index.html b/mission 9/coverage/lcov-report/tests/helpers/index.html new file mode 100644 index 000000000..477c21370 --- /dev/null +++ b/mission 9/coverage/lcov-report/tests/helpers/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for tests/helpers + + + + + + + + + +
+
+

All files tests/helpers

+
+ +
+ 81.25% + Statements + 13/16 +
+ + +
+ 66.66% + Branches + 4/6 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 81.25% + Lines + 13/16 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
auth.ts +
+
81.25%13/1666.66%4/6100%1/181.25%13/16
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov.info b/mission 9/coverage/lcov.info new file mode 100644 index 000000000..9c3e5329d --- /dev/null +++ b/mission 9/coverage/lcov.info @@ -0,0 +1,1510 @@ +TN: +SF:src/app.ts +FN:36,(anonymous_1) +FNF:1 +FNH:1 +FNDA:1,(anonymous_1) +DA:1,1 +DA:2,1 +DA:3,1 +DA:4,1 +DA:5,1 +DA:6,1 +DA:7,1 +DA:8,1 +DA:9,1 +DA:10,1 +DA:12,1 +DA:14,1 +DA:15,1 +DA:16,1 +DA:18,1 +DA:23,1 +DA:25,1 +DA:26,1 +DA:28,1 +DA:29,1 +DA:31,1 +DA:33,1 +DA:34,1 +DA:36,1 +DA:37,1 +DA:40,1 +DA:41,1 +LF:27 +LH:27 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/controllers/alertController.ts +FN:5,(anonymous_1) +FN:8,(anonymous_2) +FN:16,(anonymous_3) +FNF:3 +FNH:1 +FNDA:1,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +DA:2,1 +DA:3,1 +DA:5,1 +DA:6,1 +DA:8,1 +DA:9,0 +DA:10,0 +DA:11,0 +DA:12,0 +DA:13,0 +DA:16,1 +DA:17,0 +DA:18,0 +DA:20,0 +DA:21,0 +DA:23,0 +DA:24,0 +DA:27,0 +DA:29,0 +DA:30,0 +DA:34,0 +LF:21 +LH:6 +BRDA:9,0,0,0 +BRDA:9,0,1,0 +BRDA:17,1,0,0 +BRDA:17,1,1,0 +BRDA:23,2,0,0 +BRDA:23,2,1,0 +BRDA:29,3,0,0 +BRDA:29,3,1,0 +BRF:8 +BRH:0 +end_of_record +TN: +SF:src/controllers/articleController.ts +FN:9,(anonymous_1) +FN:21,(anonymous_2) +FN:31,(anonymous_3) +FN:42,(anonymous_4) +FN:57,(anonymous_5) +FNF:5 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +DA:2,1 +DA:3,1 +DA:4,1 +DA:6,1 +DA:8,1 +DA:10,0 +DA:11,0 +DA:13,0 +DA:14,0 +DA:15,0 +DA:17,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:27,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:38,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:49,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:58,0 +DA:59,0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:65,0 +DA:66,0 +DA:67,0 +LF:39 +LH:5 +BRDA:11,0,0,0 +BRDA:11,0,1,0 +BRDA:35,1,0,0 +BRDA:35,1,1,0 +BRDA:44,2,0,0 +BRDA:44,2,1,0 +BRDA:51,3,0,0 +BRDA:51,3,1,0 +BRDA:52,4,0,0 +BRDA:52,4,1,0 +BRDA:59,5,0,0 +BRDA:59,5,1,0 +BRDA:65,6,0,0 +BRDA:65,6,1,0 +BRDA:66,7,0,0 +BRDA:66,7,1,0 +BRF:16 +BRH:0 +end_of_record +TN: +SF:src/controllers/commentController.ts +FN:18,(anonymous_1) +FN:30,(anonymous_2) +FN:42,(anonymous_3) +FN:56,(anonymous_4) +FN:69,(anonymous_5) +FN:79,(anonymous_6) +FNF:6 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +DA:2,1 +DA:3,1 +DA:4,1 +DA:6,1 +DA:8,1 +DA:12,1 +DA:17,1 +DA:19,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:26,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:38,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:75,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:85,0 +LF:48 +LH:7 +BRDA:20,0,0,0 +BRDA:20,0,1,0 +BRDA:32,1,0,0 +BRDA:32,1,1,0 +BRDA:44,2,0,0 +BRDA:44,2,1,0 +BRDA:50,3,0,0 +BRDA:50,3,1,0 +BRDA:51,4,0,0 +BRDA:51,4,1,0 +BRDA:58,5,0,0 +BRDA:58,5,1,0 +BRDA:63,6,0,0 +BRDA:63,6,1,0 +BRDA:64,7,0,0 +BRDA:64,7,1,0 +BRF:16 +BRH:0 +end_of_record +TN: +SF:src/controllers/likeController.ts +FN:8,(anonymous_1) +FN:19,(anonymous_2) +FN:30,(anonymous_3) +FN:34,(anonymous_4) +FN:41,(anonymous_5) +FN:45,(anonymous_6) +FNF:6 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +DA:2,1 +DA:3,1 +DA:5,1 +DA:7,1 +DA:9,0 +DA:10,0 +DA:11,0 +DA:12,0 +DA:14,0 +DA:15,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:25,0 +DA:26,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:37,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:48,0 +LF:28 +LH:4 +BRDA:9,0,0,0 +BRDA:9,0,1,0 +BRDA:14,1,0,0 +BRDA:14,1,1,0 +BRDA:20,2,0,0 +BRDA:20,2,1,0 +BRDA:25,3,0,0 +BRDA:25,3,1,0 +BRDA:31,4,0,0 +BRDA:31,4,1,0 +BRDA:42,5,0,0 +BRDA:42,5,1,0 +BRF:12 +BRH:0 +end_of_record +TN: +SF:src/controllers/photoController.ts +FN:6,(anonymous_1) +FNF:1 +FNH:0 +FNDA:0,(anonymous_1) +DA:2,1 +DA:3,1 +DA:5,1 +DA:7,0 +DA:9,0 +DA:10,0 +DA:13,0 +DA:14,0 +DA:16,0 +DA:21,0 +DA:26,0 +LF:11 +LH:3 +BRDA:7,0,0,0 +BRDA:7,0,1,0 +BRDA:9,1,0,0 +BRDA:9,1,1,0 +BRF:4 +BRH:0 +end_of_record +TN: +SF:src/controllers/productController.ts +FN:9,(anonymous_1) +FN:20,(anonymous_2) +FN:30,(anonymous_3) +FN:41,(anonymous_4) +FN:56,(anonymous_5) +FNF:5 +FNH:2 +FNDA:1,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +DA:2,1 +DA:3,1 +DA:4,1 +DA:6,1 +DA:8,1 +DA:10,1 +DA:11,1 +DA:12,1 +DA:13,1 +DA:14,1 +DA:16,0 +DA:21,1 +DA:22,1 +DA:23,1 +DA:24,1 +DA:26,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:37,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:48,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:63,0 +DA:64,0 +DA:65,0 +LF:39 +LH:14 +BRDA:11,0,0,0 +BRDA:11,0,1,1 +BRDA:34,1,0,0 +BRDA:34,1,1,0 +BRDA:43,2,0,0 +BRDA:43,2,1,0 +BRDA:50,3,0,0 +BRDA:50,3,1,0 +BRDA:51,4,0,0 +BRDA:51,4,1,0 +BRDA:58,5,0,0 +BRDA:58,5,1,0 +BRDA:63,6,0,0 +BRDA:63,6,1,0 +BRDA:64,7,0,0 +BRDA:64,7,1,0 +BRF:16 +BRH:1 +end_of_record +TN: +SF:src/controllers/userController.ts +FN:10,(anonymous_1) +FN:23,(anonymous_2) +FN:36,(anonymous_3) +FN:46,(anonymous_4) +FN:60,(anonymous_5) +FN:73,(anonymous_6) +FN:86,(anonymous_7) +FN:93,(anonymous_8) +FNF:8 +FNH:1 +FNDA:0,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:0,(anonymous_8) +DA:2,1 +DA:3,1 +DA:4,1 +DA:5,1 +DA:7,1 +DA:9,1 +DA:11,0 +DA:12,0 +DA:13,0 +DA:14,0 +DA:16,0 +DA:17,0 +DA:19,0 +DA:24,1 +DA:26,1 +DA:27,1 +DA:28,1 +DA:30,1 +DA:32,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:47,0 +DA:48,0 +DA:50,0 +DA:51,0 +DA:53,0 +DA:55,0 +DA:56,0 +DA:61,0 +DA:62,0 +DA:64,0 +DA:65,0 +DA:67,0 +DA:69,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:80,0 +DA:82,0 +DA:87,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:94,0 +DA:95,0 +LF:50 +LH:11 +BRDA:16,0,0,0 +BRDA:16,0,1,0 +BRDA:24,1,0,0 +BRDA:24,1,1,1 +BRDA:38,2,0,0 +BRDA:38,2,1,0 +BRDA:48,3,0,0 +BRDA:48,3,1,0 +BRDA:55,4,0,0 +BRDA:55,4,1,0 +BRDA:62,5,0,0 +BRDA:62,5,1,0 +BRDA:75,6,0,0 +BRDA:75,6,1,0 +BRDA:77,7,0,0 +BRDA:77,7,1,0 +BRDA:77,8,0,0 +BRDA:77,8,1,0 +BRDA:87,9,0,0 +BRDA:87,9,1,0 +BRF:20 +BRH:1 +end_of_record +TN: +SF:src/dtos/article.dto.ts +FN:30,(anonymous_0) +FN:35,(anonymous_1) +FNF:2 +FNH:0 +FNDA:0,(anonymous_0) +FNDA:0,(anonymous_1) +DA:1,1 +DA:4,1 +DA:14,1 +DA:25,1 +DA:30,0 +DA:35,0 +LF:6 +LH:4 +BRDA:35,0,0,0 +BRDA:35,0,1,0 +BRF:2 +BRH:0 +end_of_record +TN: +SF:src/dtos/product.dto.ts +FN:24,(anonymous_0) +FN:25,(anonymous_1) +FNF:2 +FNH:2 +FNDA:1,(anonymous_0) +FNDA:1,(anonymous_1) +DA:1,1 +DA:5,1 +DA:14,1 +DA:23,1 +DA:24,1 +DA:25,1 +LF:6 +LH:6 +BRDA:25,0,0,1 +BRDA:25,0,1,1 +BRF:2 +BRH:2 +end_of_record +TN: +SF:src/dtos/user.dto.ts +FNF:0 +FNH:0 +DA:1,1 +DA:4,1 +DA:12,1 +DA:19,1 +DA:26,1 +LF:5 +LH:5 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/lib/constants.ts +FNF:0 +FNH:0 +DA:1,2 +DA:3,2 +DA:5,2 +DA:6,2 +DA:8,2 +DA:10,2 +DA:11,2 +DA:12,2 +DA:15,2 +DA:16,2 +DA:17,2 +DA:18,2 +DA:19,2 +DA:20,2 +LF:14 +LH:14 +BRDA:5,0,0,2 +BRDA:5,0,1,0 +BRDA:6,1,0,2 +BRDA:6,1,1,0 +BRDA:8,2,0,2 +BRDA:8,2,1,0 +BRDA:10,3,0,2 +BRDA:10,3,1,0 +BRF:8 +BRH:4 +end_of_record +TN: +SF:src/lib/cookieUtil.ts +FN:4,setTokenCookies +FN:19,clearTokenCookies +FNF:2 +FNH:1 +FNDA:1,setTokenCookies +FNDA:0,clearTokenCookies +DA:2,1 +DA:4,1 +DA:5,1 +DA:11,1 +DA:19,1 +DA:20,0 +DA:21,0 +LF:7 +LH:5 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/lib/prisma.ts +FNF:0 +FNH:0 +DA:1,6 +DA:3,6 +DA:5,6 +LF:3 +LH:3 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/lib/token.ts +FN:7,generateTokens +FN:17,verifyAccessToken +FN:22,verifyRefreshToken +FNF:3 +FNH:1 +FNDA:1,generateTokens +FNDA:0,verifyAccessToken +FNDA:0,verifyRefreshToken +DA:1,2 +DA:2,2 +DA:8,1 +DA:11,1 +DA:14,1 +DA:18,0 +DA:19,0 +DA:23,0 +DA:24,0 +DA:27,2 +LF:10 +LH:6 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/lib/passport/index.ts +FNF:0 +FNH:0 +DA:1,1 +DA:2,1 +DA:3,1 +DA:5,1 +DA:6,1 +DA:7,1 +DA:9,1 +LF:7 +LH:7 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/lib/passport/jwtStrategy.ts +FN:22,(anonymous_1) +FN:29,(anonymous_2) +FN:33,jwtVerify +FNF:3 +FNH:2 +FNDA:1,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:1,jwtVerify +DA:1,1 +DA:2,1 +DA:5,1 +DA:21,1 +DA:23,1 +DA:28,1 +DA:29,0 +DA:34,1 +DA:35,1 +DA:38,1 +DA:40,0 +DA:44,1 +DA:49,1 +LF:13 +LH:11 +BRDA:23,0,0,1 +BRDA:23,0,1,1 +BRF:2 +BRH:2 +end_of_record +TN: +SF:src/lib/passport/localStrategy.ts +FN:10,(anonymous_1) +FNF:1 +FNH:1 +FNDA:1,(anonymous_1) +DA:1,1 +DA:2,1 +DA:3,1 +DA:5,1 +DA:11,1 +DA:12,1 +DA:13,1 +DA:14,0 +DA:17,1 +DA:18,1 +DA:19,0 +DA:22,1 +DA:24,0 +LF:13 +LH:10 +BRDA:13,0,0,0 +BRDA:13,0,1,1 +BRDA:18,1,0,0 +BRDA:18,1,1,1 +BRF:4 +BRH:2 +end_of_record +TN: +SF:src/middlewares/errorHandler.ts +FN:9,errorHandler +FNF:1 +FNH:0 +FNDA:0,errorHandler +DA:1,1 +DA:2,1 +DA:9,1 +DA:10,0 +DA:11,0 +DA:14,0 +DA:15,0 +DA:18,0 +DA:19,0 +LF:9 +LH:3 +BRDA:10,0,0,0 +BRDA:10,0,1,0 +BRDA:14,1,0,0 +BRDA:14,1,1,0 +BRF:4 +BRH:0 +end_of_record +TN: +SF:src/repositories/alertRepository.ts +FN:4,(anonymous_1) +FN:8,(anonymous_2) +FN:15,(anonymous_3) +FN:22,(anonymous_4) +FN:28,(anonymous_5) +FNF:5 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +DA:1,3 +DA:3,3 +DA:5,0 +DA:9,0 +DA:16,0 +DA:23,0 +DA:29,0 +LF:7 +LH:2 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/repositories/articleRepository.ts +FN:5,(anonymous_1) +FN:9,(anonymous_2) +FN:19,(anonymous_3) +FN:26,(anonymous_4) +FN:34,(anonymous_5) +FNF:5 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +DA:1,1 +DA:4,1 +DA:6,0 +DA:10,0 +DA:20,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:31,0 +DA:35,0 +DA:39,1 +LF:11 +LH:3 +BRDA:28,0,0,0 +BRDA:28,0,1,0 +BRDA:29,1,0,0 +BRDA:29,1,1,0 +BRF:4 +BRH:0 +end_of_record +TN: +SF:src/repositories/commentRepository.ts +FN:4,(anonymous_1) +FN:10,(anonymous_2) +FN:16,(anonymous_3) +FN:20,(anonymous_4) +FN:27,(anonymous_5) +FN:31,(anonymous_6) +FN:41,(anonymous_7) +FNF:7 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +DA:1,1 +DA:3,1 +DA:5,0 +DA:11,0 +DA:17,0 +DA:21,0 +DA:28,0 +DA:32,0 +DA:42,0 +DA:52,1 +LF:10 +LH:3 +BRDA:35,0,0,0 +BRDA:35,0,1,0 +BRDA:36,1,0,0 +BRDA:36,1,1,0 +BRDA:45,2,0,0 +BRDA:45,2,1,0 +BRDA:46,3,0,0 +BRDA:46,3,1,0 +BRF:8 +BRH:0 +end_of_record +TN: +SF:src/repositories/likeRepository.ts +FN:4,(anonymous_1) +FN:8,(anonymous_2) +FN:12,(anonymous_3) +FN:18,(anonymous_4) +FN:24,(anonymous_5) +FN:31,(anonymous_6) +FN:38,(anonymous_7) +FN:44,(anonymous_8) +FN:50,(anonymous_9) +FN:59,(anonymous_10) +FN:68,(anonymous_11) +FN:83,(anonymous_12) +FNF:12 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:0,(anonymous_9) +FNDA:0,(anonymous_10) +FNDA:0,(anonymous_11) +FNDA:0,(anonymous_12) +DA:1,2 +DA:3,2 +DA:5,0 +DA:9,0 +DA:13,0 +DA:19,0 +DA:25,0 +DA:32,0 +DA:39,0 +DA:45,0 +DA:51,0 +DA:60,0 +DA:69,0 +DA:83,0 +LF:14 +LH:2 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/repositories/productRepository.ts +FN:6,(anonymous_1) +FN:10,(anonymous_2) +FN:27,(anonymous_3) +FN:42,(anonymous_4) +FN:46,(anonymous_5) +FNF:5 +FNH:2 +FNDA:1,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +DA:1,2 +DA:5,2 +DA:7,1 +DA:11,1 +DA:28,0 +DA:43,0 +DA:47,0 +LF:7 +LH:4 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/repositories/userRepository.ts +FN:4,(anonymous_1) +FN:8,(anonymous_2) +FN:15,(anonymous_3) +FN:19,(anonymous_4) +FN:23,(anonymous_5) +FNF:5 +FNH:1 +FNDA:1,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +DA:1,2 +DA:3,2 +DA:5,1 +DA:9,0 +DA:16,0 +DA:20,0 +DA:24,0 +LF:7 +LH:3 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/routers/alertRouter.ts +FNF:0 +FNH:0 +DA:1,1 +DA:2,1 +DA:3,1 +DA:5,1 +DA:6,1 +DA:8,1 +DA:10,1 +DA:12,1 +LF:8 +LH:8 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/routers/articleRouter.ts +FNF:0 +FNH:0 +DA:1,1 +DA:2,1 +DA:3,1 +DA:5,1 +DA:6,1 +DA:8,1 +DA:9,1 +DA:10,1 +DA:12,1 +DA:13,1 +DA:15,1 +LF:11 +LH:11 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/routers/commentRouter.ts +FNF:0 +FNH:0 +DA:1,1 +DA:2,1 +DA:3,1 +DA:5,1 +DA:6,1 +DA:9,1 +DA:10,1 +DA:11,1 +DA:12,1 +DA:15,1 +DA:16,1 +DA:18,1 +LF:12 +LH:12 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/routers/index.ts +FNF:0 +FNH:0 +DA:1,1 +DA:3,1 +DA:4,1 +DA:5,1 +DA:6,1 +DA:7,1 +DA:8,1 +DA:9,1 +DA:11,1 +DA:13,1 +DA:14,1 +DA:15,1 +DA:16,1 +DA:17,1 +DA:18,1 +DA:19,1 +DA:21,1 +LF:17 +LH:17 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/routers/likeRouter.ts +FNF:0 +FNH:0 +DA:1,1 +DA:2,1 +DA:3,1 +DA:5,1 +DA:6,1 +DA:8,1 +DA:9,1 +DA:10,1 +DA:11,1 +DA:13,1 +LF:10 +LH:10 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/routers/photoRouter.ts +FNF:0 +FNH:0 +DA:1,1 +DA:2,1 +DA:3,1 +DA:4,1 +DA:6,1 +DA:7,1 +DA:8,1 +DA:10,1 +DA:17,1 +LF:9 +LH:9 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/routers/productRouter.ts +FNF:0 +FNH:0 +DA:1,1 +DA:2,1 +DA:3,1 +DA:5,1 +DA:6,1 +DA:9,1 +DA:10,1 +DA:11,1 +DA:14,1 +DA:15,1 +DA:17,1 +LF:11 +LH:11 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/routers/userRouter.ts +FNF:0 +FNH:0 +DA:1,1 +DA:2,1 +DA:3,1 +DA:5,1 +DA:6,1 +DA:8,1 +DA:9,1 +DA:10,1 +DA:11,1 +DA:12,1 +DA:13,1 +DA:14,1 +DA:15,1 +DA:17,1 +LF:14 +LH:14 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/services/alertService.ts +FN:4,(anonymous_0) +FN:7,(anonymous_1) +FN:16,(anonymous_2) +FN:20,(anonymous_3) +FN:34,(anonymous_4) +FNF:5 +FNH:3 +FNDA:6,(anonymous_0) +FNDA:1,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:2,(anonymous_3) +FNDA:0,(anonymous_4) +DA:1,3 +DA:2,3 +DA:4,3 +DA:5,6 +DA:8,1 +DA:10,1 +DA:11,1 +DA:13,1 +DA:17,0 +DA:21,2 +DA:23,2 +DA:25,2 +DA:26,1 +DA:29,1 +DA:31,1 +DA:35,0 +LF:16 +LH:14 +BRDA:23,0,0,0 +BRDA:23,0,1,2 +BRDA:25,1,0,1 +BRDA:25,1,1,1 +BRF:4 +BRH:3 +end_of_record +TN: +SF:src/services/articleService.ts +FN:5,(anonymous_0) +FN:8,(anonymous_1) +FN:12,(anonymous_2) +FN:25,(anonymous_3) +FN:29,(anonymous_4) +FN:37,(anonymous_5) +FNF:6 +FNH:1 +FNDA:2,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +DA:1,1 +DA:5,1 +DA:6,2 +DA:9,0 +DA:13,0 +DA:22,0 +DA:26,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:34,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:46,1 +LF:16 +LH:4 +BRDA:13,0,0,0 +BRDA:13,0,1,0 +BRDA:31,1,0,0 +BRDA:31,1,1,0 +BRDA:32,2,0,0 +BRDA:32,2,1,0 +BRDA:39,3,0,0 +BRDA:39,3,1,0 +BRDA:40,4,0,0 +BRDA:40,4,1,0 +BRF:10 +BRH:0 +end_of_record +TN: +SF:src/services/commentService.ts +FN:6,(anonymous_0) +FN:12,(anonymous_1) +FN:39,(anonymous_2) +FN:66,(anonymous_3) +FN:73,(anonymous_4) +FN:80,(anonymous_5) +FN:84,(anonymous_6) +FNF:7 +FNH:1 +FNDA:1,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +DA:1,1 +DA:2,1 +DA:3,1 +DA:4,1 +DA:6,1 +DA:7,1 +DA:8,1 +DA:9,1 +DA:10,1 +DA:17,0 +DA:18,0 +DA:19,0 +DA:22,0 +DA:28,0 +DA:29,0 +DA:36,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:49,0 +DA:55,0 +DA:56,0 +DA:63,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:81,0 +DA:85,0 +LF:33 +LH:9 +BRDA:18,0,0,0 +BRDA:18,0,1,0 +BRDA:28,1,0,0 +BRDA:28,1,1,0 +BRDA:28,2,0,0 +BRDA:28,2,1,0 +BRDA:45,3,0,0 +BRDA:45,3,1,0 +BRDA:55,4,0,0 +BRDA:55,4,1,0 +BRDA:55,5,0,0 +BRDA:55,5,1,0 +BRDA:68,6,0,0 +BRDA:68,6,1,0 +BRDA:69,7,0,0 +BRDA:69,7,1,0 +BRDA:75,8,0,0 +BRDA:75,8,1,0 +BRDA:76,9,0,0 +BRDA:76,9,1,0 +BRF:20 +BRH:0 +end_of_record +TN: +SF:src/services/likeService.ts +FN:3,(anonymous_0) +FN:6,(anonymous_1) +FN:17,(anonymous_2) +FN:28,(anonymous_3) +FN:32,(anonymous_4) +FNF:5 +FNH:1 +FNDA:1,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +DA:1,1 +DA:3,1 +DA:4,1 +DA:7,0 +DA:8,0 +DA:10,0 +DA:11,0 +DA:12,0 +DA:14,0 +DA:18,0 +DA:19,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:25,0 +DA:29,0 +DA:33,0 +LF:17 +LH:3 +BRDA:8,0,0,0 +BRDA:8,0,1,0 +BRDA:11,1,0,0 +BRDA:11,1,1,0 +BRDA:19,2,0,0 +BRDA:19,2,1,0 +BRDA:22,3,0,0 +BRDA:22,3,1,0 +BRF:8 +BRH:0 +end_of_record +TN: +SF:src/services/productService.ts +FN:7,(anonymous_0) +FN:12,(anonymous_1) +FN:16,(anonymous_2) +FN:28,(anonymous_3) +FN:32,(anonymous_4) +FN:47,(anonymous_5) +FN:61,(anonymous_6) +FNF:7 +FNH:6 +FNDA:4,(anonymous_0) +FNDA:2,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:1,(anonymous_5) +FNDA:1,(anonymous_6) +DA:1,2 +DA:2,2 +DA:3,2 +DA:7,2 +DA:8,4 +DA:9,4 +DA:10,4 +DA:13,2 +DA:17,1 +DA:25,1 +DA:29,0 +DA:37,1 +DA:38,1 +DA:39,1 +DA:41,1 +DA:42,1 +DA:44,1 +DA:45,1 +DA:47,1 +DA:49,1 +DA:50,1 +DA:58,1 +DA:62,1 +DA:63,1 +DA:64,1 +DA:66,0 +LF:26 +LH:24 +BRDA:17,0,0,0 +BRDA:17,0,1,1 +BRDA:38,1,0,0 +BRDA:38,1,1,1 +BRDA:39,2,0,0 +BRDA:39,2,1,1 +BRDA:44,3,0,1 +BRDA:44,3,1,0 +BRDA:44,4,0,1 +BRDA:44,4,1,1 +BRDA:63,5,0,0 +BRDA:63,5,1,1 +BRDA:64,6,0,1 +BRDA:64,6,1,0 +BRF:14 +BRH:8 +end_of_record +TN: +SF:src/services/userService.ts +FN:6,(anonymous_1) +FN:9,(anonymous_2) +FN:20,(anonymous_3) +FN:24,(anonymous_4) +FN:34,(anonymous_5) +FN:41,(anonymous_6) +FN:45,(anonymous_7) +FNF:7 +FNH:3 +FNDA:4,(anonymous_1) +FNDA:2,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:2,(anonymous_7) +DA:1,2 +DA:2,2 +DA:3,2 +DA:6,2 +DA:7,4 +DA:10,2 +DA:11,2 +DA:13,1 +DA:14,1 +DA:16,1 +DA:17,1 +DA:21,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:29,0 +DA:31,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:42,0 +DA:46,2 +LF:23 +LH:12 +BRDA:11,0,0,1 +BRDA:11,0,1,1 +BRDA:26,1,0,0 +BRDA:26,1,1,0 +BRDA:27,2,0,0 +BRDA:27,2,1,0 +BRDA:29,3,0,0 +BRDA:29,3,1,0 +BRF:8 +BRH:2 +end_of_record +TN: +SF:src/socket/io.ts +FN:5,initIo +FN:15,getIo +FNF:2 +FNH:2 +FNDA:1,initIo +FNDA:1,getIo +DA:1,3 +DA:3,3 +DA:5,3 +DA:6,1 +DA:12,1 +DA:15,3 +DA:16,1 +DA:17,0 +DA:19,1 +LF:9 +LH:8 +BRDA:16,0,0,0 +BRDA:16,0,1,1 +BRF:2 +BRH:1 +end_of_record +TN: +SF:src/socket/socket.ts +FN:4,registerSocket +FN:7,(anonymous_2) +FNF:2 +FNH:1 +FNDA:1,registerSocket +FNDA:0,(anonymous_2) +DA:1,1 +DA:2,1 +DA:4,1 +DA:5,1 +DA:7,1 +DA:8,0 +DA:10,0 +DA:11,0 +DA:13,0 +DA:14,0 +DA:18,0 +DA:20,0 +LF:12 +LH:5 +BRDA:11,0,0,0 +BRDA:11,0,1,0 +BRF:2 +BRH:0 +end_of_record +TN: +SF:tests/helpers/auth.ts +FN:12,loginAndGetToken +FNF:1 +FNH:1 +FNDA:1,loginAndGetToken +DA:2,1 +DA:3,1 +DA:4,1 +DA:5,1 +DA:12,1 +DA:16,1 +DA:19,1 +DA:22,1 +DA:23,0 +DA:24,0 +DA:28,1 +DA:33,1 +DA:36,1 +DA:37,1 +DA:38,0 +DA:41,1 +LF:16 +LH:13 +BRDA:13,0,0,1 +BRDA:14,1,0,1 +BRDA:22,2,0,0 +BRDA:22,2,1,1 +BRDA:37,3,0,0 +BRDA:37,3,1,1 +BRF:6 +BRH:4 +end_of_record diff --git a/mission 9/jest.config.ts b/mission 9/jest.config.ts index 91c17246c..ab6e15598 100644 --- a/mission 9/jest.config.ts +++ b/mission 9/jest.config.ts @@ -1,9 +1,15 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ module.exports = { + preset: 'ts-jest', testEnvironment: 'node', - verbose: true, - testMatch: ['**/*.test.ts'], - transform: { - '^.+\\.ts$': 'ts-jest', + roots: ['/tests'], + moduleNameMapper: { + '^@/(.*)$': '/src/$1', // 경로 alias 사용 시 }, - moduleFileExtensions: ['ts', 'js'], -}; \ No newline at end of file + setupFilesAfterEnv: [], + clearMocks: true, + restoreMocks: true, + collectCoverage: true, + coverageDirectory: '/coverage', + coverageReporters: ['text', 'lcov'], +}; diff --git a/mission 9/package.json b/mission 9/package.json index 19bbf159c..5b700ce87 100644 --- a/mission 9/package.json +++ b/mission 9/package.json @@ -8,7 +8,8 @@ "lint": "eslint . --ext .ts", "prisma:generate": "prisma generate", "prisma:migrate": "prisma migrate dev", - "test": "jest" + "test": "jest --coverage", + "test:watch": "jest --watch" }, "author": "", "license": "ISC", diff --git a/mission 9/src/app.ts b/mission 9/src/app.ts index acb330d7d..4982c2969 100644 --- a/mission 9/src/app.ts +++ b/mission 9/src/app.ts @@ -6,40 +6,36 @@ import passport from "./lib/passport/index"; import cors from "cors"; import { errorHandler } from "./middlewares/errorHandler"; import http from "http"; -import { Server } from "socket.io"; -import { registerSocket } from "./socket"; +import { initIo } from "./socket/io"; // ⬅ io 초기화 함수만 import +import { registerSocket } from "./socket/socket"; // ⬅ 소켓 이벤트 등록 const app = express(); app.use(express.urlencoded({ extended: true })); - app.use(express.json()); app.use(cookieParser()); const corsOptions = { origin: "http://localhost:3000", - optionSuccessStatus: 200, + optionsSuccessStatus: 200, + credentials: true, }; app.use(cors(corsOptions)); app.use(passport.initialize()); app.use(router); + app.use("/download", express.static("uploads")); app.use(errorHandler); const server = http.createServer(app); -const io = new Server(server, { - cors: { - origin: "http://localhost:3000", - methods: ["GET", "POST"], - }, -}); - -registerSocket(io); - -export { io }; +initIo(server); +registerSocket(); -app.listen(PORT, () => { +server.listen(PORT, () => { console.log(`Server is running on http://localhost:${PORT}`); }); + +export { app }; +export default app; \ No newline at end of file diff --git a/mission 9/src/controllers/alertController.ts b/mission 9/src/controllers/alertController.ts index 4399fb677..058502c17 100644 --- a/mission 9/src/controllers/alertController.ts +++ b/mission 9/src/controllers/alertController.ts @@ -14,8 +14,23 @@ export class AlertController { }; markAsRead = async (req: Request, res: Response) => { + if (!req.user) + return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const userId = req.user.id; const alertId = Number(req.params.id); - await this.service.read(alertId); + + if (!alertId) { + throw new Error("Article not found"); + } + + const success = await this.service.read(alertId, userId); + + if (!success) { + return res.status(status.FORBIDDEN).json({ + message: "You do not have permission to read this alert", + }); + } res.status(204).send(); }; } diff --git a/mission 9/src/controllers/userController.ts b/mission 9/src/controllers/userController.ts index 8f706c6b5..e6c61a7ac 100644 --- a/mission 9/src/controllers/userController.ts +++ b/mission 9/src/controllers/userController.ts @@ -26,7 +26,8 @@ export class UserController { try { const { accessToken, refreshToken } = userService.generateUserTokens(req.user.id); setTokenCookies(res, accessToken, refreshToken); - res.status(status.OK).json({ token: accessToken, refreshToken }); + + res.status(status.OK).json({ accessToken, refreshToken }); } catch (err) { next(err); } diff --git a/mission 9/src/lib/passport/jwtStrategy.ts b/mission 9/src/lib/passport/jwtStrategy.ts index 7d258318c..3561a8013 100644 --- a/mission 9/src/lib/passport/jwtStrategy.ts +++ b/mission 9/src/lib/passport/jwtStrategy.ts @@ -1,4 +1,4 @@ -import { Strategy as JwtStrategy } from 'passport-jwt'; +import { Strategy as JwtStrategy, ExtractJwt } from 'passport-jwt'; import prisma from '../prisma'; import type { Request } from 'express'; import type { VerifiedCallback } from 'passport-jwt'; @@ -13,8 +13,15 @@ interface JwtPayload { sub: number; } +// const accessTokenOptions = { +// jwtFromRequest: (req: Request) => req.cookies[ACCESS_TOKEN_COOKIE_NAME], +// secretOrKey: JWT_ACCESS_TOKEN_SECRET, +// }; + const accessTokenOptions = { - jwtFromRequest: (req: Request) => req.cookies[ACCESS_TOKEN_COOKIE_NAME], + jwtFromRequest: (req: Request) => { + return req.cookies[ACCESS_TOKEN_COOKIE_NAME] || ExtractJwt.fromAuthHeaderAsBearerToken()(req); + }, secretOrKey: JWT_ACCESS_TOKEN_SECRET, }; diff --git a/mission 9/src/repositories/alertRepository.ts b/mission 9/src/repositories/alertRepository.ts index 71d7bf1e6..53fc4281c 100644 --- a/mission 9/src/repositories/alertRepository.ts +++ b/mission 9/src/repositories/alertRepository.ts @@ -24,4 +24,10 @@ export class AlertRepository { where: { userId, isRead: false }, }); } + + async findById(id: number) { + return prisma.alert.findUnique({ + where: { id }, + }); + } } diff --git a/mission 9/src/routers/alertRouter.ts b/mission 9/src/routers/alertRouter.ts index c461c7cb3..bfca71a29 100644 --- a/mission 9/src/routers/alertRouter.ts +++ b/mission 9/src/routers/alertRouter.ts @@ -5,10 +5,8 @@ import { AlertController } from "../controllers/alertController"; const router = express.Router(); const controller = new AlertController(); -// 내 알림 조회 router.get("/", passport.authenticate("access-token", { session: false }), controller.list); -// 알림 읽음 처리 router.patch("/:id/read", passport.authenticate("access-token", { session: false }), controller.markAsRead); export default router; diff --git a/mission 9/src/routers/articleRouter.ts b/mission 9/src/routers/articleRouter.ts index 4c4161a6b..d61bb9072 100644 --- a/mission 9/src/routers/articleRouter.ts +++ b/mission 9/src/routers/articleRouter.ts @@ -6,9 +6,10 @@ const router = express.Router(); const controller = new ArticleController(); router.post("/", passport.authenticate("access-token", { session: false }), controller.create); -router.get("/", passport.authenticate("access-token", { session: false }), controller.list); -router.get("/:id", passport.authenticate("access-token", { session: false }), controller.detail); router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update); router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete); -export default router; \ No newline at end of file +router.get("/", controller.list); +router.get("/:id", controller.detail); + +export default router; diff --git a/mission 9/src/routers/commentRouter.ts b/mission 9/src/routers/commentRouter.ts index f7b6b4903..017c71b63 100644 --- a/mission 9/src/routers/commentRouter.ts +++ b/mission 9/src/routers/commentRouter.ts @@ -5,11 +5,14 @@ import { CommentController } from "../controllers/commentController"; const router = express.Router(); const controller = new CommentController(); +// Private router.post("/products/:id", passport.authenticate("access-token", { session: false }), controller.createProductComment); router.post("/articles/:id", passport.authenticate("access-token", { session: false }), controller.createArticleComment); router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.modifyComment); router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.deleteComment); -router.get("/products/:id", passport.authenticate("access-token", { session: false }), controller.productCommentList); -router.get("/articles/:id", passport.authenticate("access-token", { session: false }), controller.articleCommentList); -export default router; \ No newline at end of file +// Public +router.get("/products/:id", controller.productCommentList); +router.get("/articles/:id", controller.articleCommentList); + +export default router; diff --git a/mission 9/src/routers/index.ts b/mission 9/src/routers/index.ts index 82c6b975b..3ecb392d1 100644 --- a/mission 9/src/routers/index.ts +++ b/mission 9/src/routers/index.ts @@ -5,7 +5,7 @@ import articleRouter from "./articleRouter"; import productRouter from "./productRouter"; import commentRouter from "./commentRouter"; import likeRouter from "./likeRouter"; -import photoRouter from "./photoRouter"; // ✅ 공통 업로드 전용 +import photoRouter from "./photoRouter"; import alertRouter from "./alertRouter"; const router = express.Router(); @@ -15,7 +15,7 @@ router.use("/articles", articleRouter); router.use("/products", productRouter); router.use("/comments", commentRouter); router.use("/likes", likeRouter); -router.use(photoRouter); // 📌 prefix는 /photos +router.use(photoRouter); router.use("/alerts", alertRouter); export default router; \ No newline at end of file diff --git a/mission 9/src/routers/productRouter.ts b/mission 9/src/routers/productRouter.ts index 63f2d5d87..5b4e02623 100644 --- a/mission 9/src/routers/productRouter.ts +++ b/mission 9/src/routers/productRouter.ts @@ -5,10 +5,13 @@ import { ProductController } from "../controllers/productController"; const router = express.Router(); const controller = new ProductController(); +// ✅ 인증 필요 router.post("/", passport.authenticate("access-token", { session: false }), controller.create); -router.get("/", controller.list); -router.get("/:id", passport.authenticate("access-token", { session: false }), controller.list); router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update); router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete); -export default router; \ No newline at end of file +// ✅ 인증 필요 X (공개) +router.get("/", controller.list); +router.get("/:id", controller.detail); + +export default router; diff --git a/mission 9/src/services/alertService.ts b/mission 9/src/services/alertService.ts index b9d89c23f..e604bb94a 100644 --- a/mission 9/src/services/alertService.ts +++ b/mission 9/src/services/alertService.ts @@ -1,5 +1,5 @@ import { AlertRepository } from "../repositories/alertRepository"; -import { io } from "../app"; +import { getIo } from "../socket/io"; export class AlertService { private repo = new AlertRepository(); @@ -7,6 +7,7 @@ export class AlertService { async create(userId: number, message: string, link?: string) { const alert = await this.repo.createAlert({ userId, message, link }); + const io = getIo(); io.to(`user:${userId}`).emit("newAlert", alert); return alert; @@ -16,8 +17,18 @@ export class AlertService { return this.repo.findByUserId(userId); } - async read(alertId: number) { - return this.repo.markAsRead(alertId); + async read(alertId: number, userId: number) { + const alert = await this.repo.findById(alertId); + + if (!alert) return false; + + if (alert.userId !== userId) { + return false; + } + + await this.repo.markAsRead(alertId); + + return true; } async countUnread(userId: number) { diff --git a/mission 9/src/services/commentService.ts b/mission 9/src/services/commentService.ts index e3eb961b5..eec34093f 100644 --- a/mission 9/src/services/commentService.ts +++ b/mission 9/src/services/commentService.ts @@ -14,12 +14,16 @@ export class CommentService { articleId: number, content: string ) { + const article = await this.articleRepo.findById(articleId); + if (!article) { + throw new Error("Article not found"); + } + const comment = await this.repo.createArticleComment( userId, articleId, content ); - const article = await this.articleRepo.findById(articleId); if (article && article.userId !== userId) { await this.alertService.create( @@ -37,12 +41,16 @@ export class CommentService { productId: number, content: string ) { + const product = await this.productRepo.findById(productId); + if (!product) { + throw new Error("Product not found"); + } + const comment = await this.repo.createProductComment( userId, productId, content ); - const product = await this.productRepo.findById(productId); if (product && product.userId !== userId) { await this.alertService.create( diff --git a/mission 9/src/services/productService.ts b/mission 9/src/services/productService.ts index 0b2890163..d4b931371 100644 --- a/mission 9/src/services/productService.ts +++ b/mission 9/src/services/productService.ts @@ -49,7 +49,7 @@ export class ProductService { for (const user of targetUsers) { await this.alertService.create( user.id, - `좋아요한 상품 "${product.name}"의 가격이 ${oldPrice}원 → ${data.price}원으로 변경되었습니다.`, + `좋아요한 상품 "${updated.name}"의 가격이 ${oldPrice}원 → ${data.price}원으로 변경되었습니다.`, `/products/${productId}` ); } diff --git a/mission 9/src/socket.ts b/mission 9/src/socket.ts deleted file mode 100644 index 087568b1f..000000000 --- a/mission 9/src/socket.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Server } from "socket.io"; - -export function registerSocket(io: Server) { - io.on("connection", (socket) => { - console.log("New client connected:", socket.id); - - socket.on("register", (userId: number) => { - socket.join(`user:${userId}`); - console.log(`User ${userId} joined room user:${userId}`); - }); - - socket.on("disconnect", () => { - console.log("Client disconnected:", socket.id); - }); - }); -} \ No newline at end of file diff --git a/mission 9/src/socket/io.ts b/mission 9/src/socket/io.ts new file mode 100644 index 000000000..4af5cf407 --- /dev/null +++ b/mission 9/src/socket/io.ts @@ -0,0 +1,20 @@ +import { Server } from "socket.io"; + +let io: Server | null = null; + +export function initIo(server: any) { + io = new Server(server, { + cors: { + origin: "http://localhost:3000", + methods: ["GET", "POST"], + }, + }); + return io; +} + +export function getIo(): Server { + if (!io) { + throw new Error("Socket.io has not been initialized!"); + } + return io; +} diff --git a/mission 9/src/socket/socket.ts b/mission 9/src/socket/socket.ts new file mode 100644 index 000000000..677718145 --- /dev/null +++ b/mission 9/src/socket/socket.ts @@ -0,0 +1,23 @@ +import { getIo } from "./io"; +import jwt from "jsonwebtoken"; + +export function registerSocket() { + const io = getIo(); // <-- initIo에서 만든 io 가져오기 + + io.on("connection", (socket) => { + console.log("Socket connected:", socket.id); + + const token = socket.handshake.auth?.token; + if (!token) return socket.disconnect(); + + try { + const decoded = jwt.verify(token, process.env.JWT_SECRET!) as { + id: number; + }; + + socket.join(`user:${decoded.id}`); + } catch (err) { + socket.disconnect(); + } + }); +} diff --git a/mission 9/test/articleService.test.ts b/mission 9/test/articleService.test.ts deleted file mode 100644 index 230de9b9d..000000000 --- a/mission 9/test/articleService.test.ts +++ /dev/null @@ -1,125 +0,0 @@ -// mock 선언은 import보다 위에 있어야 함 -jest.mock("../src/repositories/articleRepository", () => { - return { - ArticleRepository: jest.fn().mockImplementation(() => ({ - createArticle: jest.fn(), - findMany: jest.fn(), - findById: jest.fn(), - updatedArticle: jest.fn(), - deleteArticle: jest.fn(), - })), - }; -}); - -import articleService, { ArticleService } from "../src/services/articleService"; -import { ArticleRepository } from "../src/repositories/articleRepository"; - -// 타입 추론을 위해 any 대신 명시적 타입 사용 -const repoMock = new ArticleRepository() as jest.Mocked; - -describe("ArticleService", () => { - const mockArticle = { - id: 1, - userId: 1, - title: "테스트 제목", - content: "테스트 내용", - createdAt: new Date(), - updatedAt: new Date(), - }; - - beforeEach(() => { - jest.clearAllMocks(); - // articleService 내부 repo를 mock으로 덮어씀 - (articleService as any).repo = repoMock; - }); - - it("should create an article", async () => { - repoMock.createArticle.mockResolvedValue(mockArticle); - - const result = await articleService.create(1, { - title: "테스트 제목", - content: "테스트 내용", - }); - - expect(result).toEqual(mockArticle); - expect(repoMock.createArticle).toHaveBeenCalledWith({ - title: "테스트 제목", - content: "테스트 내용", - userId: 1, - }); - }); - - it("should list articles with pagination and keyword", async () => { - repoMock.findMany.mockResolvedValue([mockArticle]); - - const result = await articleService.list({ - page: 1, - pageSize: 10, - keyword: "테스트", - }); - - expect(result).toEqual([mockArticle]); - expect(repoMock.findMany).toHaveBeenCalled(); - }); - - it("should get detail of an article", async () => { - repoMock.findById.mockResolvedValue(mockArticle); - - const result = await articleService.getDetail(1); - - expect(result).toEqual(mockArticle); - expect(repoMock.findById).toHaveBeenCalledWith(1); - }); - - it("should update article if user owns it", async () => { - repoMock.findById.mockResolvedValue(mockArticle); - repoMock.updatedArticle.mockResolvedValue({ - ...mockArticle, - title: "수정된 제목", - }); - - const result = await articleService.update(1, { title: "수정된 제목" }, 1); - - expect(result.title).toBe("수정된 제목"); - expect(repoMock.updatedArticle).toHaveBeenCalledWith(1, { - title: "수정된 제목", - }); - }); - - it("should throw FORBIDDEN if another user tries to update", async () => { - repoMock.findById.mockResolvedValue({ ...mockArticle, userId: 999 }); - - await expect( - articleService.update(1, { title: "수정된 제목" }, 1) - ).rejects.toThrow("FORBIDDEN"); - }); - - it("should throw NOT_FOUND if article does not exist on update", async () => { - repoMock.findById.mockResolvedValue(null); - - await expect( - articleService.update(1, { title: "없는 글" }, 1) - ).rejects.toThrow("NOT_FOUND"); - }); - - it("should delete article if user owns it", async () => { - repoMock.findById.mockResolvedValue(mockArticle); - repoMock.deleteArticle.mockResolvedValue(undefined); - - await articleService.delete(1, 1); - - expect(repoMock.deleteArticle).toHaveBeenCalledWith(1); - }); - - it("should throw FORBIDDEN if another user tries to delete", async () => { - repoMock.findById.mockResolvedValue({ ...mockArticle, userId: 999 }); - - await expect(articleService.delete(1, 1)).rejects.toThrow("FORBIDDEN"); - }); - - it("should throw NOT_FOUND if article not found on delete", async () => { - repoMock.findById.mockResolvedValue(null); - - await expect(articleService.delete(1, 1)).rejects.toThrow("NOT_FOUND"); - }); -}); diff --git a/mission 9/test/commentService.test.ts b/mission 9/test/commentService.test.ts deleted file mode 100644 index bff9f6120..000000000 --- a/mission 9/test/commentService.test.ts +++ /dev/null @@ -1,203 +0,0 @@ -// --- mock setup (import보다 위에 위치해야 함) --- -jest.mock("../src/repositories/commentRepository", () => ({ - CommentRepository: jest.fn().mockImplementation(() => ({ - createArticleComment: jest.fn(), - createProductComment: jest.fn(), - findById: jest.fn(), - updateComment: jest.fn(), - deleteComment: jest.fn(), - findProductComments: jest.fn(), - findArticleComments: jest.fn(), - })), -})); - -jest.mock("../src/repositories/articleRepository", () => ({ - ArticleRepository: jest.fn().mockImplementation(() => ({ - findById: jest.fn(), - })), -})); - -jest.mock("../src/repositories/productRepository", () => ({ - ProductRepository: jest.fn().mockImplementation(() => ({ - findById: jest.fn(), - })), -})); - -jest.mock("../src/services/alertService", () => ({ - AlertService: jest.fn().mockImplementation(() => ({ - create: jest.fn(), - })), -})); - -// --- imports --- -import { CommentService } from "../src/services/commentService"; -import { CommentRepository } from "../src/repositories/commentRepository"; -import { ArticleRepository } from "../src/repositories/articleRepository"; -import { ProductRepository } from "../src/repositories/productRepository"; -import { AlertService } from "../src/services/alertService"; - -// --- mocks --- -const commentRepoMock = new CommentRepository() as jest.Mocked; -const articleRepoMock = new ArticleRepository() as jest.Mocked; -const productRepoMock = new ProductRepository() as jest.Mocked; -const alertServiceMock = new AlertService() as jest.Mocked; - -describe("CommentService", () => { - let service: CommentService; - - const mockComment = { - id: 1, - userId: 1, - content: "테스트 댓글", - articleId: 1, - productId: null, - createdAt: new Date(), - }; - - const mockArticle = { - id: 1, - userId: 2, - title: "게시글 제목", - content: "내용", - createdAt: new Date(), - updatedAt: new Date(), - }; - - const mockProduct = { - id: 1, - userId: 2, - name: "상품 이름", - description: "상품 설명", - price: 1000, - tags: null, - createdAt: new Date(), - updatedAt: new Date(), - }; - - beforeEach(() => { - jest.clearAllMocks(); - service = new CommentService(); - - // service 내부 repo 교체 - (service as any).repo = commentRepoMock; - (service as any).articleRepo = articleRepoMock; - (service as any).productRepo = productRepoMock; - (service as any).alertService = alertServiceMock; - }); - - // ✅ Article 댓글 생성 테스트 - it("should create article comment and trigger alert to article owner", async () => { - commentRepoMock.createArticleComment.mockResolvedValue(mockComment); - articleRepoMock.findById.mockResolvedValue(mockArticle); - - const result = await service.createArticleComment(1, 1, "테스트 댓글"); - - expect(result).toEqual(mockComment); - expect(commentRepoMock.createArticleComment).toHaveBeenCalledWith(1, 1, "테스트 댓글"); - expect(alertServiceMock.create).toHaveBeenCalledWith( - 2, - "내 게시글에 새로운 댓글이 달렸습니다.", - "/articles/1" - ); - }); - - it("should not trigger alert if commenter is article owner", async () => { - articleRepoMock.findById.mockResolvedValue({ ...mockArticle, userId: 1 }); - commentRepoMock.createArticleComment.mockResolvedValue(mockComment); - - await service.createArticleComment(1, 1, "테스트 댓글"); - - expect(alertServiceMock.create).not.toHaveBeenCalled(); - }); - - // ✅ Product 댓글 생성 테스트 - it("should create product comment and trigger alert to product owner", async () => { - commentRepoMock.createProductComment.mockResolvedValue(mockComment); - productRepoMock.findById.mockResolvedValue(mockProduct); - - const result = await service.createProductComment(1, 1, "테스트 댓글"); - - expect(result).toEqual(mockComment); - expect(alertServiceMock.create).toHaveBeenCalledWith( - 2, - "내 판매글에 새로운 댓글이 달렸습니다.", - "/products/1" - ); - }); - - it("should not trigger alert if commenter is product owner", async () => { - productRepoMock.findById.mockResolvedValue({ ...mockProduct, userId: 1 }); - commentRepoMock.createProductComment.mockResolvedValue(mockComment); - - await service.createProductComment(1, 1, "테스트 댓글"); - - expect(alertServiceMock.create).not.toHaveBeenCalled(); - }); - - // ✅ 댓글 수정 테스트 - it("should update comment if user owns it", async () => { - commentRepoMock.findById.mockResolvedValue(mockComment); - commentRepoMock.updateComment.mockResolvedValue({ - ...mockComment, - content: "수정된 댓글", - }); - - const result = await service.updateComment(1, 1, "수정된 댓글"); - - expect(result.content).toBe("수정된 댓글"); - expect(commentRepoMock.updateComment).toHaveBeenCalledWith(1, "수정된 댓글"); - }); - - it("should throw FORBIDDEN if another user tries to update", async () => { - commentRepoMock.findById.mockResolvedValue({ ...mockComment, userId: 999 }); - - await expect(service.updateComment(1, 1, "수정된 댓글")).rejects.toThrow("FORBIDDEN"); - }); - - it("should throw NOT_FOUND if comment does not exist on update", async () => { - commentRepoMock.findById.mockResolvedValue(null); - - await expect(service.updateComment(1, 1, "없음")).rejects.toThrow("NOT_FOUND"); - }); - - // ✅ 댓글 삭제 테스트 - it("should delete comment if user owns it", async () => { - commentRepoMock.findById.mockResolvedValue(mockComment); - commentRepoMock.deleteComment.mockResolvedValue(undefined as any); - - await service.deleteComment(1, 1); - - expect(commentRepoMock.deleteComment).toHaveBeenCalledWith(1); - }); - - it("should throw FORBIDDEN if another user tries to delete", async () => { - commentRepoMock.findById.mockResolvedValue({ ...mockComment, userId: 999 }); - - await expect(service.deleteComment(1, 1)).rejects.toThrow("FORBIDDEN"); - }); - - it("should throw NOT_FOUND if comment not found on delete", async () => { - commentRepoMock.findById.mockResolvedValue(null); - - await expect(service.deleteComment(1, 1)).rejects.toThrow("NOT_FOUND"); - }); - - // ✅ 댓글 목록 조회 테스트 - it("should get product comments", async () => { - commentRepoMock.findProductComments.mockResolvedValue([mockComment]); - - const result = await service.getProductComments(1); - - expect(result).toEqual([mockComment]); - expect(commentRepoMock.findProductComments).toHaveBeenCalledWith(1, undefined); - }); - - it("should get article comments", async () => { - commentRepoMock.findArticleComments.mockResolvedValue([mockComment]); - - const result = await service.getArticleComments(1); - - expect(result).toEqual([mockComment]); - expect(commentRepoMock.findArticleComments).toHaveBeenCalledWith(1, undefined); - }); -}); diff --git a/mission 9/test/hello.test.ts b/mission 9/test/hello.test.ts deleted file mode 100644 index fe78c37be..000000000 --- a/mission 9/test/hello.test.ts +++ /dev/null @@ -1,4 +0,0 @@ -test('안녕 Jest', () => { - const value = 'Hello Jest'; - expect(value).toEqual('Hello Jest'); -}); \ No newline at end of file diff --git a/mission 9/test/productService.test.ts b/mission 9/test/productService.test.ts deleted file mode 100644 index f8fb8e36a..000000000 --- a/mission 9/test/productService.test.ts +++ /dev/null @@ -1,121 +0,0 @@ -// ✅ 1. 반드시 import보다 위에 있어야 함 -jest.mock("../src/repositories/productRepository", () => { - return { - ProductRepository: jest.fn().mockImplementation(() => ({ - createProduct: jest.fn(), - findMany: jest.fn(), - findById: jest.fn(), - updateProduct: jest.fn(), - deleteProduct: jest.fn(), - })), - }; -}); - -import { ProductService } from "../src/services/productService"; -import { ProductRepository } from "../src/repositories/productRepository"; - -describe("ProductService", () => { - let service: ProductService; - let repoMock: jest.Mocked; - - const mockProduct = { - id: 1, - name: "Laptop", - description: "Fast laptop", - price: 2000, - tags: "tech", - userId: 10, - createdAt: new Date(), - updatedAt: new Date(), - }; - - beforeEach(() => { - jest.clearAllMocks(); - service = new ProductService(); - repoMock = service["repo"] as jest.Mocked; - }); - - // ✅ create - it("should create a new product", async () => { - const input = { name: "Phone", description: "Smartphone", price: 1000, tags: "mobile" }; - const created = { ...mockProduct, ...input, id: 2 }; - repoMock.createProduct.mockResolvedValue(created as any); - - const result = await service.create(10, input); - - expect(repoMock.createProduct).toHaveBeenCalledWith({ ...input, userId: 10 }); - expect(result).toEqual(created); - }); - - // ✅ list - it("should list products with keyword filter", async () => { - repoMock.findMany.mockResolvedValue([mockProduct] as any); - - const result = await service.list({ page: 1, pageSize: 10, keyword: "Laptop" }); - - expect(repoMock.findMany).toHaveBeenCalled(); - expect(result).toEqual([mockProduct]); - }); - - // ✅ getDetail - it("should get product detail", async () => { - repoMock.findById.mockResolvedValue(mockProduct as any); - - const result = await service.getDetail(1); - - expect(repoMock.findById).toHaveBeenCalledWith(1); - expect(result).toEqual(mockProduct); - }); - - // ✅ update - success - it("should update product if user owns it", async () => { - repoMock.findById.mockResolvedValue(mockProduct as any); - const updated = { ...mockProduct, name: "Updated Laptop" }; - repoMock.updateProduct.mockResolvedValue(updated as any); - - const result = await service.update(10, 1, { name: "Updated Laptop" }); - - expect(repoMock.findById).toHaveBeenCalledWith(1); - expect(repoMock.updateProduct).toHaveBeenCalledWith(1, { name: "Updated Laptop" }); - expect(result).toEqual(updated); - }); - - // ✅ update - not found - it("should throw NOT_FOUND when product not found", async () => { - repoMock.findById.mockResolvedValue(null); - - await expect(service.update(10, 1, { name: "Updated" })).rejects.toThrow("NOT_FOUND"); - }); - - // ✅ update - forbidden - it("should throw FORBIDDEN when user does not own product", async () => { - repoMock.findById.mockResolvedValue({ ...mockProduct, userId: 99 } as any); - - await expect(service.update(10, 1, { name: "Updated" })).rejects.toThrow("FORBIDDEN"); - }); - - // ✅ delete - success - it("should delete product if user owns it", async () => { - repoMock.findById.mockResolvedValue(mockProduct as any); - repoMock.deleteProduct.mockResolvedValue(undefined as any); - - await service.delete(10, 1); - - expect(repoMock.findById).toHaveBeenCalledWith(1); - expect(repoMock.deleteProduct).toHaveBeenCalledWith(1); - }); - - // ✅ delete - not found - it("should throw NOT_FOUND if product does not exist", async () => { - repoMock.findById.mockResolvedValue(null); - - await expect(service.delete(10, 1)).rejects.toThrow("NOT_FOUND"); - }); - - // ✅ delete - forbidden - it("should throw FORBIDDEN if user does not own product", async () => { - repoMock.findById.mockResolvedValue({ ...mockProduct, userId: 99 } as any); - - await expect(service.delete(10, 1)).rejects.toThrow("FORBIDDEN"); - }); -}); diff --git a/mission 9/tests/_mocks_/alertRepository.ts b/mission 9/tests/_mocks_/alertRepository.ts new file mode 100644 index 000000000..398de8955 --- /dev/null +++ b/mission 9/tests/_mocks_/alertRepository.ts @@ -0,0 +1,7 @@ +export class AlertRepository { + createAlert = jest.fn(); + findByUserId = jest.fn(); + findById = jest.fn(); + markAsRead = jest.fn(); + countUnread = jest.fn(); +} diff --git a/mission 9/tests/_mocks_/productRepository.ts b/mission 9/tests/_mocks_/productRepository.ts new file mode 100644 index 000000000..f92c1cbd4 --- /dev/null +++ b/mission 9/tests/_mocks_/productRepository.ts @@ -0,0 +1,7 @@ +export class ProductRepository { + createProduct = jest.fn(); + findMany = jest.fn(); + findById = jest.fn(); + updateProduct = jest.fn(); + deleteProduct = jest.fn(); +} diff --git a/mission 9/tests/_mocks_/userRepositoy.ts b/mission 9/tests/_mocks_/userRepositoy.ts new file mode 100644 index 000000000..261bcb3f0 --- /dev/null +++ b/mission 9/tests/_mocks_/userRepositoy.ts @@ -0,0 +1,7 @@ +export class UserRepository { + createUser = jest.fn(); + findByEmail = jest.fn(); + findById = jest.fn(); + updateUser = jest.fn(); + findProductsByUserId = jest.fn(); +} diff --git a/mission 9/tests/alertService.test.ts b/mission 9/tests/alertService.test.ts new file mode 100644 index 000000000..01cba5ae5 --- /dev/null +++ b/mission 9/tests/alertService.test.ts @@ -0,0 +1,60 @@ +import { AlertService } from "../src/services/alertService"; +import { AlertRepository } from "../src/repositories/alertRepository"; +import { getIo } from "../src/socket/io"; + +jest.mock("../src/repositories/alertRepository"); +jest.mock("../src/socket/io"); + +describe("AlertService", () => { + let service: AlertService; + let repo: jest.Mocked; + + beforeEach(() => { + service = new AlertService(); + repo = service["repo"] as any; + (getIo as jest.Mock).mockReturnValue({ + to: jest.fn().mockReturnThis(), + emit: jest.fn(), + }); + }); + + it("알림 생성", async () => { + repo.createAlert.mockResolvedValue({ + id: 1, + userId: 1, + message: "테스트", + link: null, + createdAt: new Date(), + isRead: false, + }); + const alert = await service.create(1, "테스트"); + expect(alert).toHaveProperty("id"); + expect(getIo().to).toHaveBeenCalled(); + }); + + it("알림 읽기 권한 검증", async () => { + repo.findById.mockResolvedValue({ + id: 1, + userId: 2, + message: "테스트", + link: null, + createdAt: new Date(), + isRead: false, + }); + const result = await service.read(1, 2); + expect(result).toBe(true); + }); + + it("권한 없는 경우 읽기 실패", async () => { + repo.findById.mockResolvedValue({ + id: 1, + userId: 2, + message: "테스트", + link: null, + createdAt: new Date(), + isRead: false, + }); + const result = await service.read(1, 3); + expect(result).toBe(false); + }); +}); diff --git a/mission 9/tests/helpers/auth.ts b/mission 9/tests/helpers/auth.ts new file mode 100644 index 000000000..597f9674b --- /dev/null +++ b/mission 9/tests/helpers/auth.ts @@ -0,0 +1,42 @@ +// tests/helpers/auth.ts +import request from "supertest"; +import { app } from "../../src/app"; +import bcrypt from "bcrypt"; +import { UserRepository } from "../../src/repositories/userRepository"; + +interface TokenResponse { + accessToken: string; + refreshToken?: string; +} + +export async function loginAndGetToken( + email = "test@test.com", + password = "123456" +): Promise { + const userRepo = new UserRepository(); + + // 1️⃣ 테스트용 유저 확인 + let existing = await userRepo.findByEmail(email); + + // 2️⃣ 없으면 생성 + if (!existing) { + const hashed = await bcrypt.hash(password, 10); + existing = await userRepo.createUser(email, "tester", hashed); + } + + // 3️⃣ 로그인 요청 + const res = await request(app) + .post("/users/login") + .send({ email, password }) + .expect(200); + + console.log("Login response body:", res.body); // 디버깅용 + + // 4️⃣ 로그인 성공 시 accessToken 반환 + const { accessToken, refreshToken } = res.body; + if (!accessToken) { + throw new Error("로그인 실패: accessToken이 반환되지 않았습니다."); + } + + return { accessToken, refreshToken }; +} diff --git a/mission 9/tests/product.integration.test.ts b/mission 9/tests/product.integration.test.ts new file mode 100644 index 000000000..492dfe66d --- /dev/null +++ b/mission 9/tests/product.integration.test.ts @@ -0,0 +1,45 @@ +// tests/product.integration.test.ts +import request from "supertest"; +import { app } from "../src/app"; +import { loginAndGetToken } from "./helpers/auth"; + +describe("상품 API 통합 테스트", () => { + let accessToken: string; + + beforeAll(async () => { + // 테스트용 계정 로그인 및 토큰 발급 + const tokens = await loginAndGetToken(); + accessToken = tokens.accessToken; + }); + + it("인증 필요 상품 생성", async () => { + const res = await request(app) + .post("/products") // 실제 라우트 확인 필요 + .set("Authorization", `Bearer ${accessToken}`) + .send({ + name: "테스트상품", + price: 1000, + description: "테스트용 상품입니다", // 10자 이상 필수 + tags: "테스트", + }) + .expect(201); // 성공 예상 + + expect(res.body).toHaveProperty("id"); + expect(res.body.name).toBe("테스트상품"); + expect(res.body.price).toBe(1000); + expect(res.body.description).toBe("테스트용 상품입니다"); + }); + + it("인증 필요 상품 조회", async () => { + const res = await request(app) + .get("/products") + .set("Authorization", `Bearer ${accessToken}`) + .expect(200); + + expect(Array.isArray(res.body)).toBe(true); + expect(res.body.length).toBeGreaterThan(0); + expect(res.body[0]).toHaveProperty("name"); + expect(res.body[0]).toHaveProperty("price"); + expect(res.body[0]).toHaveProperty("description"); + }); +}); diff --git a/mission 9/tests/productService.test.ts b/mission 9/tests/productService.test.ts new file mode 100644 index 000000000..149bb2c38 --- /dev/null +++ b/mission 9/tests/productService.test.ts @@ -0,0 +1,89 @@ +import { ProductService } from "../src/services/productService"; +import { ProductRepository } from "../src/repositories/productRepository"; +import { LikeRepository } from "../src/repositories/likeRepository"; +import { AlertService } from "../src/services/alertService"; + +jest.mock("../src/repositories/productRepository"); +jest.mock("../src/repositories/likeRepository"); +jest.mock("../src/services/alertService"); + +describe("ProductService", () => { + let service: ProductService; + let productRepo: jest.Mocked; + let likeRepo: jest.Mocked; + let alertService: jest.Mocked; + + beforeEach(() => { + service = new ProductService(); + productRepo = service["repo"] as any; + likeRepo = service["likeRepo"] as any; + alertService = service["alertService"] as any; + }); + + it("상품 생성", async () => { + productRepo.createProduct.mockResolvedValue({ + id: 1, + userId: 1, + name: "상품", + description: "설명", + price: 1000, + tags: null, + createdAt: new Date(), + updatedAt: new Date(), + }); + const res = await service.create(1, { + name: "상품", + price: 1000, + description: "설명", + } as any); + expect(res).toEqual({ + id: 1, + userId: 1, + name: "상품", + description: "설명", + price: 1000, + tags: null, + createdAt: expect.any(Date), + updatedAt: expect.any(Date), + }); + expect(productRepo.createProduct).toHaveBeenCalled(); + }); + + it("상품 가격 변경 시 알림 생성", async () => { + const oldProduct = { + id: 1, + userId: 2, + name: "상품", + description: "테스트 상품 설명", + price: 1000, + tags: null, + createdAt: new Date(), + updatedAt: new Date(), + }; + productRepo.findById.mockResolvedValue(oldProduct); + productRepo.updateProduct.mockResolvedValue({ ...oldProduct, price: 2000 }); + likeRepo.findUsersWhoLikedProduct.mockResolvedValue([ + { id: 3, nickname: "alice" }, + ]); + + await service.update(2, 1, { price: 2000 }); + expect(alertService.create).toHaveBeenCalledWith( + 3, + expect.stringContaining("상품"), + "/products/1" + ); + }); + + it("본인 아닌 경우 삭제 권한 검증", async () => { + productRepo.findById.mockResolvedValue({ + id: 1, + userId: 2, + name: "상품", + description: "테스트 상품 설명", + price: 1000, + tags: null, + createdAt: new Date(), + }); + await expect(service.delete(3, 1)).rejects.toThrow("FORBIDDEN"); + }); +}); diff --git a/mission 9/tests/userService.test.ts b/mission 9/tests/userService.test.ts new file mode 100644 index 000000000..4a51aabe6 --- /dev/null +++ b/mission 9/tests/userService.test.ts @@ -0,0 +1,65 @@ +// import bcrypt from "bcrypt"; +import { UserService } from "../src/services/userService"; +import { UserRepository } from "../src/repositories/userRepository"; +import { generateTokens } from "../src/lib/token"; + +jest.mock("../src/repositories/userRepository"); +jest.mock("../src/lib/token"); + +describe("UserService", () => { + let service: UserService; + let userRepo: jest.Mocked; + + beforeEach(() => { + service = new UserService(); + userRepo = service["userRepo"] as any; + }); + + it("회원가입 성공", async () => { + userRepo.findByEmail.mockResolvedValue(null); + userRepo.createUser.mockResolvedValue({ + id: 1, + email: "test@test.com", + nickname: "tester", + password: "hashed_password", + image: null, + createdAt: new Date(), + updatedAt: new Date(), + }); + const res = await service.register({ + email: "a@test.com", + password: "123", + nickname: "nick", + }); + expect(res).toHaveProperty("message"); + expect(userRepo.createUser).toHaveBeenCalled(); + }); + + it("회원가입 중복 이메일", async () => { + userRepo.findByEmail.mockResolvedValue({ + id: 1, + email: "a@test.com", + nickname: "tester", + password: "hashed", + image: null, + createdAt: new Date(), + updatedAt: new Date(), + }); + await expect( + service.register({ + email: "a@test.com", + password: "123", + nickname: "nick", + }) + ).rejects.toThrow("EMAIL_EXISTS"); + }); + + it("JWT 토큰 생성", () => { + (generateTokens as jest.Mock).mockReturnValue({ + accessToken: "token", + refreshToken: "refresh", + }); + const tokens = service.generateUserTokens(1); + expect(tokens).toHaveProperty("accessToken"); + }); +}); From 87a9c96a4862608b716102f94c9385ac36e7a794 Mon Sep 17 00:00:00 2001 From: Batur-s Date: Fri, 14 Nov 2025 15:32:20 +0900 Subject: [PATCH 32/38] [feat] modify test to supertest --- mission 9/coverage/lcov-report/index.html | 160 +-- .../coverage/lcov-report/src/app.ts.html | 74 +- .../src/controllers/alertController.ts.html | 14 +- .../src/controllers/articleController.ts.html | 118 +- .../src/controllers/commentController.ts.html | 16 +- .../lcov-report/src/controllers/index.html | 82 +- .../src/controllers/likeController.ts.html | 10 +- .../src/controllers/photoController.ts.html | 8 +- .../src/controllers/productController.ts.html | 122 +- .../src/controllers/userController.ts.html | 66 +- .../lcov-report/src/dtos/article.dto.ts.html | 36 +- .../coverage/lcov-report/src/dtos/index.html | 40 +- .../lcov-report/src/dtos/product.dto.ts.html | 10 +- .../lcov-report/src/dtos/user.dto.ts.html | 12 +- mission 9/coverage/lcov-report/src/index.html | 14 +- .../lcov-report/src/lib/constants.ts.html | 30 +- .../lcov-report/src/lib/cookieUtil.ts.html | 12 +- .../coverage/lcov-report/src/lib/index.html | 2 +- .../lcov-report/src/lib/passport/index.html | 32 +- .../src/lib/passport/index.ts.html | 16 +- .../src/lib/passport/jwtStrategy.ts.html | 24 +- .../src/lib/passport/localStrategy.ts.html | 40 +- .../lcov-report/src/lib/prisma.ts.html | 8 +- .../lcov-report/src/lib/token.ts.html | 14 +- .../src/middlewares/errorHandler.ts.html | 8 +- .../lcov-report/src/middlewares/index.html | 2 +- .../src/repositories/alertRepository.ts.html | 6 +- .../repositories/articleRepository.ts.html | 68 +- .../repositories/commentRepository.ts.html | 8 +- .../lcov-report/src/repositories/index.html | 90 +- .../src/repositories/likeRepository.ts.html | 28 +- .../repositories/productRepository.ts.html | 38 +- .../src/repositories/userRepository.ts.html | 28 +- .../src/routers/alertRouter.ts.html | 18 +- .../src/routers/articleRouter.ts.html | 24 +- .../src/routers/commentRouter.ts.html | 32 +- .../lcov-report/src/routers/index.html | 30 +- .../lcov-report/src/routers/index.ts.html | 36 +- .../src/routers/likeRouter.ts.html | 22 +- .../src/routers/photoRouter.ts.html | 20 +- .../src/routers/productRouter.ts.html | 24 +- .../src/routers/userRouter.ts.html | 190 ++- .../src/services/alertService.ts.html | 10 +- .../src/services/articleService.ts.html | 82 +- .../src/services/commentService.ts.html | 20 +- .../lcov-report/src/services/index.html | 56 +- .../src/services/likeService.ts.html | 8 +- .../src/services/productService.ts.html | 50 +- .../src/services/userService.ts.html | 14 +- .../lcov-report/src/socket/index.html | 2 +- .../lcov-report/src/socket/io.ts.html | 14 +- .../lcov-report/src/socket/socket.ts.html | 12 +- .../lcov-report/tests/helpers/auth.ts.html | 64 +- .../lcov-report/tests/helpers/db.ts.html | 112 ++ .../lcov-report/tests/helpers/index.html | 47 +- mission 9/coverage/lcov.info | 1056 +++++++++-------- mission 9/src/app.ts | 12 +- mission 9/src/routers/commentRouter.ts | 2 - mission 9/src/routers/userRouter.ts | 58 +- mission 9/src/server.ts | 6 + mission 9/tests/article.integration.test.ts | 70 ++ mission 9/tests/helpers/auth.ts | 14 +- mission 9/tests/helpers/db.ts | 9 + mission 9/tests/product.integration.test.ts | 90 +- mission 9/tests/productService.test.ts | 89 -- mission 9/tests/user.integration.test.ts | 76 ++ mission 9/tests/userService.test.ts | 65 - 67 files changed, 2020 insertions(+), 1650 deletions(-) create mode 100644 mission 9/coverage/lcov-report/tests/helpers/db.ts.html create mode 100644 mission 9/src/server.ts create mode 100644 mission 9/tests/article.integration.test.ts create mode 100644 mission 9/tests/helpers/db.ts delete mode 100644 mission 9/tests/productService.test.ts create mode 100644 mission 9/tests/user.integration.test.ts delete mode 100644 mission 9/tests/userService.test.ts diff --git a/mission 9/coverage/lcov-report/index.html b/mission 9/coverage/lcov-report/index.html index ae89673b9..f22f4fe58 100644 --- a/mission 9/coverage/lcov-report/index.html +++ b/mission 9/coverage/lcov-report/index.html @@ -23,30 +23,30 @@

All files

- 48.37% + 58.13% Statements - 357/738 + 436/750
- 15% + 25.36% Branches - 30/200 + 52/205
- 26.15% + 43.93% Functions - 34/130 + 58/132
- 52.38% + 62.9% Lines - 352/672 + 429/682
@@ -61,7 +61,7 @@

All files

-
+
@@ -84,43 +84,43 @@

All files

- + - + - + - - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + @@ -140,17 +140,17 @@

All files

- - - - - + + + + - - + + @@ -169,48 +169,48 @@

All files

- - + - - - - - - - - + + + + + + + + - + + + + - - - - - + - + - - + - - - - - - - - + + + + + + + + @@ -230,17 +230,17 @@

All files

- - - - - + + + + - - - + + + @@ -251,7 +251,7 @@

All files

+ + + + + + \ No newline at end of file diff --git a/mission 9/coverage/lcov-report/tests/helpers/index.html b/mission 9/coverage/lcov-report/tests/helpers/index.html index 477c21370..45483e936 100644 --- a/mission 9/coverage/lcov-report/tests/helpers/index.html +++ b/mission 9/coverage/lcov-report/tests/helpers/index.html @@ -23,30 +23,30 @@

All files tests/helpers

- 81.25% + 95.65% Statements - 13/16 + 22/23
- 66.66% + 71.42% Branches - 4/6 + 5/7
100% Functions - 1/1 + 2/2
- 81.25% + 95.65% Lines - 13/16 + 22/23
@@ -80,17 +80,32 @@

All files tests/helpers

- - - - - + + + + - - + + + + + + + + + + + + + + + @@ -101,7 +116,7 @@

All files tests/helpers

+ + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/prettify.css b/mission 10/coverage/lcov-report/prettify.css new file mode 100644 index 000000000..b317a7cda --- /dev/null +++ b/mission 10/coverage/lcov-report/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/mission 10/coverage/lcov-report/prettify.js b/mission 10/coverage/lcov-report/prettify.js new file mode 100644 index 000000000..b3225238f --- /dev/null +++ b/mission 10/coverage/lcov-report/prettify.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/mission 10/coverage/lcov-report/sort-arrow-sprite.png b/mission 10/coverage/lcov-report/sort-arrow-sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed68316eb3f65dec9063332d2f69bf3093bbfab GIT binary patch literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^>_9Bd!3HEZxJ@+%Qh}Z>jv*C{$p!i!8j}?a+@3A= zIAGwzjijN=FBi!|L1t?LM;Q;gkwn>2cAy-KV{dn nf0J1DIvEHQu*n~6U}x}qyky7vi4|9XhBJ7&`njxgN@xNA8m%nc literal 0 HcmV?d00001 diff --git a/mission 10/coverage/lcov-report/sorter.js b/mission 10/coverage/lcov-report/sorter.js new file mode 100644 index 000000000..4ed70ae5a --- /dev/null +++ b/mission 10/coverage/lcov-report/sorter.js @@ -0,0 +1,210 @@ +/* eslint-disable */ +var addSorting = (function() { + 'use strict'; + var cols, + currentSort = { + index: 0, + desc: false + }; + + // returns the summary table element + function getTable() { + return document.querySelector('.coverage-summary'); + } + // returns the thead element of the summary table + function getTableHeader() { + return getTable().querySelector('thead tr'); + } + // returns the tbody element of the summary table + function getTableBody() { + return getTable().querySelector('tbody'); + } + // returns the th element for nth column + function getNthColumn(n) { + return getTableHeader().querySelectorAll('th')[n]; + } + + function onFilterInput() { + const searchValue = document.getElementById('fileSearch').value; + const rows = document.getElementsByTagName('tbody')[0].children; + + // Try to create a RegExp from the searchValue. If it fails (invalid regex), + // it will be treated as a plain text search + let searchRegex; + try { + searchRegex = new RegExp(searchValue, 'i'); // 'i' for case-insensitive + } catch (error) { + searchRegex = null; + } + + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + let isMatch = false; + + if (searchRegex) { + // If a valid regex was created, use it for matching + isMatch = searchRegex.test(row.textContent); + } else { + // Otherwise, fall back to the original plain text search + isMatch = row.textContent + .toLowerCase() + .includes(searchValue.toLowerCase()); + } + + row.style.display = isMatch ? '' : 'none'; + } + } + + // loads the search box + function addSearchBox() { + var template = document.getElementById('filterTemplate'); + var templateClone = template.content.cloneNode(true); + templateClone.getElementById('fileSearch').oninput = onFilterInput; + template.parentElement.appendChild(templateClone); + } + + // loads all columns + function loadColumns() { + var colNodes = getTableHeader().querySelectorAll('th'), + colNode, + cols = [], + col, + i; + + for (i = 0; i < colNodes.length; i += 1) { + colNode = colNodes[i]; + col = { + key: colNode.getAttribute('data-col'), + sortable: !colNode.getAttribute('data-nosort'), + type: colNode.getAttribute('data-type') || 'string' + }; + cols.push(col); + if (col.sortable) { + col.defaultDescSort = col.type === 'number'; + colNode.innerHTML = + colNode.innerHTML + ''; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function(a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function(a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc + ? ' sorted-desc' + : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function() { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i = 0; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector('.sorter').parentElement; + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function() { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(); + addSearchBox(); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/mission 10/coverage/lcov-report/src/app.ts.html b/mission 10/coverage/lcov-report/src/app.ts.html new file mode 100644 index 000000000..485fcb58a --- /dev/null +++ b/mission 10/coverage/lcov-report/src/app.ts.html @@ -0,0 +1,205 @@ + + + + + + Code coverage report for src/app.ts + + + + + + + + + +
+
+

All files / src app.ts

+
+ +
+ 100% + Statements + 25/25 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 24/24 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
100%27/2725/25 100% 0/0 100%1/10/0 100%27/2724/24
src/controllers -
+
+
18.11%50/2762.17%2/9211.76%4/3421.18%50/23632.24%89/27610.86%10/9232.35%11/3436.86%87/236
src/dtos -
+
+
88.23%15/1750%2/450%2/488.23%15/17100%17/17100%4/4100%4/4100%17/17
src/lib/passport -
+
+
84.84%28/3366.66%4/687.87%29/3383.33%5/6 75% 3/484.84%28/3387.87%29/33
src/repositories -
+
src/repositories +
28.81%17/590%0/127.69%3/3930.35%17/5654.23%32/5916.66%2/1233.33%13/3955.35%31/56
src/routers -
+
+
98.98%98/9975%3/4 100%92/92100%0/0100%0/02/2 100%92/9298/98
src/services -
+
src/services +
45.69%69/15120.31%13/6440.54%15/3750.38%66/13151.65%78/15128.12%18/6448.64%18/3758.77%77/131
tests/helpers -
+
+
81.25%13/1666.66%4/695.65%22/2371.42%5/7 100%1/181.25%13/162/295.65%22/23
auth.ts -
+
+
81.25%13/1666.66%4/694.11%16/1771.42%5/7 100% 1/181.25%13/1694.11%16/17
db.ts +
+
100%6/6100%0/0100%1/1100%6/6
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +413x +3x +3x +3x +3x +3x +3x +3x +3x +  +3x +  +3x +3x +3x +  +3x +  +  +  +  +3x +  +3x +3x +  +3x +  +3x +  +3x +  +3x +3x +  +  +  +  +  +3x +3x
import express from "express";
+import cookieParser from "cookie-parser";
+import router from "./routers/index";
+import passport from "./lib/passport/index";
+import cors from "cors";
+import { errorHandler } from "./middlewares/errorHandler";
+import http from "http";
+import { initIo } from "./socket/io"; // ⬅ io 초기화 함수만 import
+import { registerSocket } from "./socket/socket"; // ⬅ 소켓 이벤트 등록
+ 
+const app = express();
+ 
+app.use(express.urlencoded({ extended: true }));
+app.use(express.json());
+app.use(cookieParser());
+ 
+const corsOptions = {
+  origin: "http://localhost:3000",
+  optionsSuccessStatus: 200,
+  credentials: true,
+};
+app.use(cors(corsOptions));
+ 
+app.use(passport.initialize());
+app.use(router);
+ 
+app.use("/download", express.static("uploads"));
+ 
+app.use(errorHandler);
+ 
+const server = http.createServer(app);
+ 
+initIo(server);
+registerSocket();
+ 
+// server.listen(PORT, () => {
+//   console.log(`Server is running on http://localhost:${PORT}`);
+// });
+ 
+export { app, server };
+export default app;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/controllers/alertController.ts.html b/mission 10/coverage/lcov-report/src/controllers/alertController.ts.html new file mode 100644 index 000000000..64c467674 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/controllers/alertController.ts.html @@ -0,0 +1,193 @@ + + + + + + Code coverage report for src/controllers/alertController.ts + + + + + + + + + +
+
+

All files / src/controllers alertController.ts

+
+ +
+ 28.57% + Statements + 6/21 +
+ + +
+ 0% + Branches + 0/8 +
+ + +
+ 33.33% + Functions + 1/3 +
+ + +
+ 28.57% + Lines + 6/21 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37  +3x +3x +  +3x +3x +  +3x +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { Request, Response } from "express";
+import { AlertService } from "../services/alertService";
+import status from "http-status";
+ 
+export class AlertController {
+  private service = new AlertService();
+ 
+  list = async (req: Request, res: Response) => {
+    if (!req.user)
+      return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+    const userId = req.user.id;
+    const alerts = await this.service.list(userId);
+    res.json(alerts);
+  };
+ 
+  markAsRead = async (req: Request, res: Response) => {
+    if (!req.user)
+      return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+ 
+    const userId = req.user.id;
+    const alertId = Number(req.params.id);
+ 
+    if (!alertId) {
+      throw new Error("Article not found");
+    }
+ 
+    const success = await this.service.read(alertId, userId);
+ 
+    if (!success) {
+      return res.status(status.FORBIDDEN).json({
+        message: "You do not have permission to read this alert",
+      });
+    }
+    res.status(204).send();
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/controllers/articleController.ts.html b/mission 10/coverage/lcov-report/src/controllers/articleController.ts.html new file mode 100644 index 000000000..9e12634ab --- /dev/null +++ b/mission 10/coverage/lcov-report/src/controllers/articleController.ts.html @@ -0,0 +1,295 @@ + + + + + + Code coverage report for src/controllers/articleController.ts + + + + + + + + + +
+
+

All files / src/controllers articleController.ts

+
+ +
+ 55.31% + Statements + 26/47 +
+ + +
+ 25% + Branches + 4/16 +
+ + +
+ 80% + Functions + 4/5 +
+ + +
+ 64.1% + Lines + 25/39 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71  +3x +3x +3x +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +1x +1x +  +  +  +  +  +  +2x +2x +2x +2x +1x +  +  +  +  +  +  +1x +1x +1x +1x +1x +  +1x +  +  +  +  +  +  +  +  +1x +1x +  +1x +1x +1x +  +  +  +  +  +  +  + 
import { Request, Response, NextFunction } from "express";
+import status from "http-status";
+import { ArticleService } from "../services/articleService";
+import { ArticleCreateSchema, ArticleUpdateSchema, ArticleQuerySchema } from "../dtos/article.dto";
+ 
+const articleService = new ArticleService();
+ 
+export class ArticleController {
+  async create(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+ 
+      const parsed = ArticleCreateSchema.parse(req.body);
+      const article = await articleService.create(req.user.id, parsed);
+      res.status(status.CREATED).json(article);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async list(req: Request, res: Response, next: NextFunction) {
+    try {
+      const parsed = ArticleQuerySchema.parse(req.query);
+      const articles = await articleService.list(parsed);
+      res.status(status.OK).json(articles);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async detail(req: Request, res: Response, next: NextFunction) {
+    try {
+      const articleId = Number(req.params.id);
+      const article = await articleService.getDetail(articleId);
+      if (!article) return res.status(status.NOT_FOUND).json({ message: "Article not found" });
+      res.status(status.OK).json(article);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async update(req: Request, res: Response, next: NextFunction) {
+    try {
+      Iif (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const parsed = ArticleUpdateSchema.parse(req.body) as { title?: string; content?: string; };
+      const articleId = Number(req.params.id);
+      const updated = await articleService.update(req.user.id, parsed, articleId);
+ 
+      res.status(status.OK).json(updated);
+    } catch (err: any) {
+      if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" });
+      if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" });
+      next(err);
+    }
+  }
+ 
+  async delete(req: Request, res: Response, next: NextFunction) {
+    try {
+      Iif (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+ 
+      const articleId = Number(req.params.id);
+      await articleService.delete(req.user.id, articleId);
+      res.status(status.NO_CONTENT).end();
+    } catch (err: any) {
+      if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" });
+      if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" });
+      next(err);
+    }
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/controllers/commentController.ts.html b/mission 10/coverage/lcov-report/src/controllers/commentController.ts.html new file mode 100644 index 000000000..8add22ccb --- /dev/null +++ b/mission 10/coverage/lcov-report/src/controllers/commentController.ts.html @@ -0,0 +1,346 @@ + + + + + + Code coverage report for src/controllers/commentController.ts + + + + + + + + + +
+
+

All files / src/controllers commentController.ts

+
+ +
+ 12.5% + Statements + 7/56 +
+ + +
+ 0% + Branches + 0/16 +
+ + +
+ 0% + Functions + 0/6 +
+ + +
+ 14.58% + Lines + 7/48 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88  +3x +3x +3x +  +3x +  +3x +  +  +  +3x +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import status from "http-status";
+import { CommentService } from "../services/commentService";
+ 
+const commentService = new CommentService();
+ 
+const commentSchema = z.object({
+  content: z.string().min(5).max(100),
+});
+ 
+const commentListSchema = z.object({
+  id: z.coerce.number().int().positive(),
+  lastId: z.coerce.number().int().positive().optional(),
+});
+ 
+export class CommentController {
+  async createProductComment(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const productId = Number(req.params.id);
+      const parsed = commentSchema.parse(req.body);
+      const comment = await commentService.createProductComment(req.user.id, productId, parsed.content);
+      res.status(status.CREATED).json(comment);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async createArticleComment(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const articleId = Number(req.params.id);
+      const parsed = commentSchema.parse(req.body);
+      const comment = await commentService.createArticleComment(req.user.id, articleId, parsed.content);
+      res.status(status.CREATED).json(comment);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async modifyComment(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const commentId = Number(req.params.id);
+      const parsed = commentSchema.parse(req.body);
+      const updated = await commentService.updateComment(req.user.id, commentId, parsed.content);
+      res.status(status.OK).json(updated);
+    } catch (err: any) {
+      if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Comment not found" });
+      if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" });
+      next(err);
+    }
+  }
+ 
+  async deleteComment(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const commentId = Number(req.params.id);
+      await commentService.deleteComment(req.user.id, commentId);
+      res.status(status.NO_CONTENT).end();
+    } catch (err: any) {
+      if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Comment not found" });
+      if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" });
+      next(err);
+    }
+  }
+ 
+  async productCommentList(req: Request, res: Response, next: NextFunction) {
+    try {
+      const parsed = commentListSchema.parse({ id: req.params.id, lastId: req.query.lastId });
+      const comments = await commentService.getProductComments(parsed.id, parsed.lastId);
+      res.status(status.OK).json(comments);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async articleCommentList(req: Request, res: Response, next: NextFunction) {
+    try {
+      const parsed = commentListSchema.parse({ id: req.params.id, lastId: req.query.lastId });
+      const comments = await commentService.getArticleComments(parsed.id, parsed.lastId);
+      res.status(status.OK).json(comments);
+    } catch (err) {
+      next(err);
+    }
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/controllers/index.html b/mission 10/coverage/lcov-report/src/controllers/index.html new file mode 100644 index 000000000..bfee4d984 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/controllers/index.html @@ -0,0 +1,206 @@ + + + + + + Code coverage report for src/controllers + + + + + + + + + +
+
+

All files src/controllers

+
+ +
+ 32.24% + Statements + 89/276 +
+ + +
+ 10.86% + Branches + 10/92 +
+ + +
+ 32.35% + Functions + 11/34 +
+ + +
+ 36.86% + Lines + 87/236 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
alertController.ts +
+
28.57%6/210%0/833.33%1/328.57%6/21
articleController.ts +
+
55.31%26/4725%4/1680%4/564.1%25/39
commentController.ts +
+
12.5%7/560%0/160%0/614.58%7/48
likeController.ts +
+
11.11%4/360%0/120%0/614.28%4/28
photoController.ts +
+
25%3/120%0/40%0/127.27%3/11
productController.ts +
+
55.31%26/4725%4/1680%4/564.1%25/39
userController.ts +
+
29.82%17/5710%2/2025%2/834%17/50
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/controllers/likeController.ts.html b/mission 10/coverage/lcov-report/src/controllers/likeController.ts.html new file mode 100644 index 000000000..bd4eb7c4a --- /dev/null +++ b/mission 10/coverage/lcov-report/src/controllers/likeController.ts.html @@ -0,0 +1,235 @@ + + + + + + Code coverage report for src/controllers/likeController.ts + + + + + + + + + +
+
+

All files / src/controllers likeController.ts

+
+ +
+ 11.11% + Statements + 4/36 +
+ + +
+ 0% + Branches + 0/12 +
+ + +
+ 0% + Functions + 0/6 +
+ + +
+ 14.28% + Lines + 4/28 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51  +3x +3x +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { Request, Response, NextFunction } from "express";
+import status from "http-status";
+import { LikeService } from "../services/likeService";
+ 
+const likeService = new LikeService();
+ 
+export class LikeController {
+  async likeArticle(req: Request, res: Response, next: NextFunction) {
+    if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+    try {
+      const result = await likeService.likeArticle(req.user.id, Number(req.params.id));
+      res.status(status.OK).json({ message: "Like toggled", isLiked: result.like });
+    } catch (err: any) {
+      if (err.message === "ARTICLE_NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" });
+      next(err);
+    }
+  }
+ 
+  async likeProduct(req: Request, res: Response, next: NextFunction) {
+    if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+    try {
+      const result = await likeService.likeProduct(req.user.id, Number(req.params.id));
+      res.status(status.OK).json({ message: "Like toggled", isLiked: result.like });
+    } catch (err: any) {
+      if (err.message === "PRODUCT_NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" });
+      next(err);
+    }
+  }
+ 
+  async getLikedArticles(req: Request, res: Response, next: NextFunction) {
+    if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+    try {
+      const likedArticles = await likeService.getLikedArticles(req.user.id);
+      const articles = likedArticles.map((l) => ({ ...l.article, isLiked: true }));
+      res.status(status.OK).json(articles);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async getLikedProducts(req: Request, res: Response, next: NextFunction) {
+    if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+    try {
+      const likedProducts = await likeService.getLikedProducts(req.user.id);
+      const products = likedProducts.map((l) => ({ ...l.product, isLiked: true }));
+      res.status(status.OK).json(products);
+    } catch (err) {
+      next(err);
+    }
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/controllers/photoController.ts.html b/mission 10/coverage/lcov-report/src/controllers/photoController.ts.html new file mode 100644 index 000000000..c18b188ab --- /dev/null +++ b/mission 10/coverage/lcov-report/src/controllers/photoController.ts.html @@ -0,0 +1,169 @@ + + + + + + Code coverage report for src/controllers/photoController.ts + + + + + + + + + +
+
+

All files / src/controllers photoController.ts

+
+ +
+ 25% + Statements + 3/12 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 27.27% + Lines + 3/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29  +3x +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { Request, Response, NextFunction } from "express";
+import prisma from "../lib/prisma";
+import status from "http-status";
+ 
+export class PhotoController {
+  async upload(req: Request, res: Response, next: NextFunction) {
+    if (!req.user) return res.status(401).json({ message: "Unauthorized" });
+ 
+    if (!req.file) {
+      return res.status(status.BAD_REQUEST).json({ message: "No file uploaded" });
+    }
+ 
+    try {
+      const imageUrl = `/download/${req.file.filename}`;
+ 
+      const updatedUser = await prisma.user.update({
+        where: { id: req.user.id },
+        data: { image: imageUrl },
+      });
+ 
+      res.status(status.OK).json({
+        message: "Photo uploaded successfully",
+        image: updatedUser.image,
+      });
+    } catch (err) {
+      next(err);
+    }
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/controllers/productController.ts.html b/mission 10/coverage/lcov-report/src/controllers/productController.ts.html new file mode 100644 index 000000000..c754136cb --- /dev/null +++ b/mission 10/coverage/lcov-report/src/controllers/productController.ts.html @@ -0,0 +1,286 @@ + + + + + + Code coverage report for src/controllers/productController.ts + + + + + + + + + +
+
+

All files / src/controllers productController.ts

+
+ +
+ 55.31% + Statements + 26/47 +
+ + +
+ 25% + Branches + 4/16 +
+ + +
+ 80% + Functions + 4/5 +
+ + +
+ 64.1% + Lines + 25/39 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68  +3x +3x +3x +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +1x +1x +  +  +  +  +  +  +2x +2x +2x +2x +1x +  +  +  +  +  +  +1x +1x +1x +1x +1x +  +1x +  +  +  +  +  +  +  +  +1x +1x +1x +1x +1x +  +  +  +  +  +  + 
import { Request, Response, NextFunction } from "express";
+import status from "http-status";
+import { ProductService } from "../services/productService";
+import { ProductCreateSchema, ProductUpdateSchema, ProductQuerySchema } from "../dtos/product.dto";
+ 
+const productService = new ProductService();
+ 
+export class ProductController {
+  async create(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const parsed = ProductCreateSchema.parse(req.body);
+      const product = await productService.create(req.user.id, parsed);
+      res.status(status.CREATED).json(product);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async list(req: Request, res: Response, next: NextFunction) {
+    try {
+      const parsed = ProductQuerySchema.parse(req.query);
+      const products = await productService.list(parsed);
+      res.status(status.OK).json(products);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async detail(req: Request, res: Response, next: NextFunction) {
+    try {
+      const productId = Number(req.params.id);
+      const product = await productService.getDetail(productId);
+      if (!product) return res.status(status.NOT_FOUND).json({ message: "Product not found" });
+      res.status(status.OK).json(product);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async update(req: Request, res: Response, next: NextFunction) {
+    try {
+      Iif (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const parsed = ProductUpdateSchema.parse(req.body) as { name?: string; description?: string; price?: number; tags?: string; };
+      const productId = Number(req.params.id);
+      const updated = await productService.update(req.user.id, productId, parsed);
+      
+      res.status(status.OK).json(updated);
+    } catch (err: any) {
+      if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" });
+      if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" });
+      next(err);
+    }
+  }
+ 
+  async delete(req: Request, res: Response, next: NextFunction) {
+    try {
+      Iif (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const productId = Number(req.params.id);
+      await productService.delete(req.user.id, productId);
+      res.status(status.NO_CONTENT).end();
+    } catch (err: any) {
+      if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" });
+      if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" });
+      next(err);
+    }
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/controllers/userController.ts.html b/mission 10/coverage/lcov-report/src/controllers/userController.ts.html new file mode 100644 index 000000000..3aeb4425d --- /dev/null +++ b/mission 10/coverage/lcov-report/src/controllers/userController.ts.html @@ -0,0 +1,376 @@ + + + + + + Code coverage report for src/controllers/userController.ts + + + + + + + + + +
+
+

All files / src/controllers userController.ts

+
+ +
+ 29.82% + Statements + 17/57 +
+ + +
+ 10% + Branches + 2/20 +
+ + +
+ 25% + Functions + 2/8 +
+ + +
+ 34% + Lines + 17/50 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98  +3x +3x +3x +3x +  +3x +  +3x +  +2x +2x +2x +1x +  +1x +1x +  +  +  +  +  +  +3x +  +3x +3x +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { Request, Response, NextFunction } from "express";
+import status from "http-status";
+import { UserService } from "../services/userService";
+import { setTokenCookies, clearTokenCookies } from "../lib/cookieUtil";
+import { UserRegisterSchema, UserUpdateSchema, UserPasswordSchema, UserLoginSchema } from "../dtos/user.dto";
+ 
+const userService = new UserService();
+ 
+export class UserController {
+  async register(req: Request, res: Response, next: NextFunction) {
+    try {
+      const parsed = UserRegisterSchema.parse(req.body);
+      const result = await userService.register(parsed);
+      res.status(status.CREATED).json(result);
+    } catch (err: any) {
+      Eif (err.message === "EMAIL_EXISTS") {
+        return res.status(status.CONFLICT).json({ message: "This ID already exists" });
+      }
+      next(err);
+    }
+  }
+ 
+  login(req: Request, res: Response, next: NextFunction) {
+    Iif (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+ 
+    try {
+      const { accessToken, refreshToken } = userService.generateUserTokens(req.user.id);
+      setTokenCookies(res, accessToken, refreshToken);
+      
+      res.status(status.OK).json({ accessToken, refreshToken });
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async profile(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const profile = await userService.getProfile(req.user.id);
+      res.status(status.OK).json(profile);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async modifyInformation(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+ 
+      const parsed = UserUpdateSchema.parse(req.body); // DTO 검증
+      const updatedUser = await userService.updateInformation(req.user.id, parsed.nickname, parsed.image);
+ 
+      res.status(status.OK).json({ message: "User information updated successfully", user: updatedUser });
+    } catch (err: any) {
+      if (err.message === "NO_DATA") return res.status(status.BAD_REQUEST).json({ message: "No update data provided" });
+      next(err);
+    }
+  }
+ 
+  async modifyPassword(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+ 
+      const parsed = UserPasswordSchema.parse(req.body); // DTO 검증
+      const result = await userService.updatePassword(req.user.id, parsed);
+ 
+      res.status(status.OK).json(result);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  async products(req: Request, res: Response, next: NextFunction) {
+    try {
+      if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+      const products = await userService.getProducts(req.user.id);
+      if (!products || products.length === 0) {
+        return res.status(status.NOT_FOUND).json({ message: "No product" });
+      }
+      res.status(status.OK).json(products);
+    } catch (err) {
+      next(err);
+    }
+  }
+ 
+  refreshTokens(req: Request, res: Response) {
+    if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" });
+    const { accessToken, refreshToken } = userService.generateUserTokens(req.user.id);
+    setTokenCookies(res, accessToken, refreshToken);
+    res.status(status.OK).send({ message: "Tokens refreshed" });
+  }
+ 
+  logout(req: Request, res: Response) {
+    clearTokenCookies(res);
+    res.status(status.OK).send({ message: "Logged out successfully" });
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/dtos/article.dto.ts.html b/mission 10/coverage/lcov-report/src/dtos/article.dto.ts.html new file mode 100644 index 000000000..e8875dc77 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/dtos/article.dto.ts.html @@ -0,0 +1,199 @@ + + + + + + Code coverage report for src/dtos/article.dto.ts + + + + + + + + + +
+
+

All files / src/dtos article.dto.ts

+
+ +
+ 100% + Statements + 6/6 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 6/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +393x +  +  +3x +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +1x +  +  +  +  +1x +  +  +  + 
import { z } from "zod";
+ 
+// CREATE DTO
+export const ArticleCreateSchema = z.object({
+  title: z.string().min(1, { message: "제목을 입력해주세요" }),
+  content: z
+    .string()
+    .min(10, { message: "내용은 최소 10자 이상이어야 합니다." })
+    .max(200, { message: "내용은 최대 200자까지 가능합니다." }),
+});
+export type ArticleCreateDTO = z.infer<typeof ArticleCreateSchema>;
+ 
+// UPDATE DTO (PATCH)
+export const ArticleUpdateSchema = z.object({
+  title: z.string().min(1, { message: "제목을 입력해주세요" }).optional(),
+  content: z
+    .string()
+    .min(10, { message: "내용은 최소 10자 이상이어야 합니다." })
+    .max(200, { message: "내용은 최대 200자까지 가능합니다." })
+    .optional(),
+});
+export type ArticleUpdateDTO = z.infer<typeof ArticleUpdateSchema>;
+ 
+// QUERY DTO (GET /articles)
+export const ArticleQuerySchema = z.object({
+  page: z
+    .string()
+    .default("1")
+    .transform(Number)
+    .refine((val) => val > 0, { message: "page는 1 이상의 정수여야 합니다." }),
+  pageSize: z
+    .string()
+    .default("5")
+    .transform(Number)
+    .refine((val) => val > 0 && val <= 100, { message: "pageSize는 1~100 사이여야 합니다." }),
+  keyword: z.string().default(""),
+});
+export type ArticleQueryDTO = z.infer<typeof ArticleQuerySchema>;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/dtos/index.html b/mission 10/coverage/lcov-report/src/dtos/index.html new file mode 100644 index 000000000..4a02b2eb5 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/dtos/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for src/dtos + + + + + + + + + +
+
+

All files src/dtos

+
+ +
+ 100% + Statements + 17/17 +
+ + +
+ 100% + Branches + 4/4 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 100% + Lines + 17/17 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
article.dto.ts +
+
100%6/6100%2/2100%2/2100%6/6
product.dto.ts +
+
100%6/6100%2/2100%2/2100%6/6
user.dto.ts +
+
100%5/5100%0/0100%0/0100%5/5
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/dtos/product.dto.ts.html b/mission 10/coverage/lcov-report/src/dtos/product.dto.ts.html new file mode 100644 index 000000000..997801eb9 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/dtos/product.dto.ts.html @@ -0,0 +1,166 @@ + + + + + + Code coverage report for src/dtos/product.dto.ts + + + + + + + + + +
+
+

All files / src/dtos product.dto.ts

+
+ +
+ 100% + Statements + 6/6 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 6/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +283x +  +  +  +3x +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +3x +1x +1x +  +  + 
import { z } from "zod";
+ 
+ 
+// CREATE DTO 
+export const ProductCreateSchema = z.object({
+  name: z.string().min(1, { message: "이름을 입력해주세요" }),
+  description: z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }),
+  price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }),
+  tags: z.string().default(""),
+});
+export type ProductCreateDTO = z.infer<typeof ProductCreateSchema>;
+ 
+// UPDATE DTO
+export const ProductUpdateSchema = z.object({
+  name: z.string().min(1, { message: "이름을 입력해주세요" }).optional(),
+  description: z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }).optional(),
+  price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }).optional(),
+  tags: z.string().default("").optional(),
+});
+export type ProductUpdateDTO = z.infer<typeof ProductUpdateSchema>;
+ 
+// QUERY DTO
+export const ProductQuerySchema = z.object({
+  page: z.string().default("1").transform(Number).refine((v) => v > 0),
+  pageSize: z.string().default("5").transform(Number).refine((v) => v > 0 && v <= 100),
+  keyword: z.string().default(""),
+});
+export type ProductQueryDTO = z.infer<typeof ProductQuerySchema>;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/dtos/user.dto.ts.html b/mission 10/coverage/lcov-report/src/dtos/user.dto.ts.html new file mode 100644 index 000000000..140c92508 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/dtos/user.dto.ts.html @@ -0,0 +1,172 @@ + + + + + + Code coverage report for src/dtos/user.dto.ts + + + + + + + + + +
+
+

All files / src/dtos user.dto.ts

+
+ +
+ 100% + Statements + 5/5 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 5/5 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +303x +  +  +3x +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +3x +  +  +  +  +  +  +3x +  +  +  + 
import { z } from "zod";
+ 
+// 회원가입
+export const UserRegisterSchema = z.object({
+  email: z.string().email({ message: "Invalid email" }),
+  nickname: z.string().min(2, { message: "Nickname too short" }),
+  password: z.string().min(6, { message: "Password too short" }),
+});
+export type UserRegisterDTO = z.infer<typeof UserRegisterSchema>;
+ 
+// 로그인
+export const UserLoginSchema = z.object({
+  email: z.string().email(),
+  password: z.string().min(6),
+});
+export type UserLoginDTO = z.infer<typeof UserLoginSchema>;
+ 
+// 정보 수정 (PATCH)
+export const UserUpdateSchema = z.object({
+  nickname: z.string().min(2).optional(),
+  image: z.string().url().optional(),
+});
+export type UserUpdateDTO = z.infer<typeof UserUpdateSchema>;
+ 
+// 비밀번호 수정
+export const UserPasswordSchema = z.object({
+  password: z.string().min(6, { message: "Password too short" }),
+});
+export type UserPasswordDTO = z.infer<typeof UserPasswordSchema>;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/index.html b/mission 10/coverage/lcov-report/src/index.html new file mode 100644 index 000000000..5bc7d0859 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src + + + + + + + + + +
+
+

All files src

+
+ +
+ 100% + Statements + 25/25 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 24/24 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
app.ts +
+
100%25/25100%0/0100%0/0100%24/24
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/lib/constants.ts.html b/mission 10/coverage/lcov-report/src/lib/constants.ts.html new file mode 100644 index 000000000..0121a9496 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/lib/constants.ts.html @@ -0,0 +1,148 @@ + + + + + + Code coverage report for src/lib/constants.ts + + + + + + + + + +
+
+

All files / src/lib constants.ts

+
+ +
+ 100% + Statements + 14/14 +
+ + +
+ 50% + Branches + 4/8 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 14/14 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +223x +  +3x +  +3x +3x +  +3x +  +3x +3x +3x +  +  +3x +3x +3x +3x +3x +3x +  + 
import dotenv from 'dotenv';
+ 
+dotenv.config();
+ 
+const NODE_ENV = process.env.NODE_ENV || 'development';
+const PORT = process.env.PORT || 3000;
+const JWT_ACCESS_TOKEN_SECRET =
+  process.env.JWT_ACCESS_TOKEN_SECRET || 'your_jwt_access_token_secret';
+const JWT_REFRESH_TOKEN_SECRET =
+  process.env.JWT_REFRESH_TOKEN_SECRET || 'your_jwt_refresh_token_secret';
+const ACCESS_TOKEN_COOKIE_NAME = 'access-token';
+const REFRESH_TOKEN_COOKIE_NAME = 'refresh-token';
+ 
+export {
+  NODE_ENV,
+  PORT,
+  JWT_ACCESS_TOKEN_SECRET,
+  JWT_REFRESH_TOKEN_SECRET,
+  ACCESS_TOKEN_COOKIE_NAME,
+  REFRESH_TOKEN_COOKIE_NAME,
+};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/lib/cookieUtil.ts.html b/mission 10/coverage/lcov-report/src/lib/cookieUtil.ts.html new file mode 100644 index 000000000..912b6edd6 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/lib/cookieUtil.ts.html @@ -0,0 +1,151 @@ + + + + + + Code coverage report for src/lib/cookieUtil.ts + + + + + + + + + +
+
+

All files / src/lib cookieUtil.ts

+
+ +
+ 71.42% + Statements + 5/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 50% + Functions + 1/2 +
+ + +
+ 71.42% + Lines + 5/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23  +3x +  +3x +3x +  +  +  +  +  +3x +  +  +  +  +  +  +  +3x +  +  +  + 
import { Response } from "express";
+import { ACCESS_TOKEN_COOKIE_NAME, REFRESH_TOKEN_COOKIE_NAME, NODE_ENV } from "./constants";
+ 
+export function setTokenCookies(res: Response, accessToken: string, refreshToken: string) {
+  res.cookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, {
+    httpOnly: true,
+    secure: NODE_ENV === "production",
+    maxAge: 1 * 60 * 60 * 1000, // 1시간
+  });
+ 
+  res.cookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken, {
+    httpOnly: true,
+    secure: NODE_ENV === "production",
+    maxAge: 7 * 24 * 60 * 60 * 1000, // 7일
+    path: "/users/refresh",
+  });
+}
+ 
+export function clearTokenCookies(res: Response) {
+  res.clearCookie(ACCESS_TOKEN_COOKIE_NAME);
+  res.clearCookie(REFRESH_TOKEN_COOKIE_NAME);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/lib/index.html b/mission 10/coverage/lcov-report/src/lib/index.html new file mode 100644 index 000000000..c1cc07594 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/lib/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for src/lib + + + + + + + + + +
+
+

All files src/lib

+
+ +
+ 83.33% + Statements + 30/36 +
+ + +
+ 50% + Branches + 4/8 +
+ + +
+ 40% + Functions + 2/5 +
+ + +
+ 82.35% + Lines + 28/34 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
constants.ts +
+
100%14/1450%4/8100%0/0100%14/14
cookieUtil.ts +
+
71.42%5/7100%0/050%1/271.42%5/7
prisma.ts +
+
100%3/3100%0/0100%0/0100%3/3
token.ts +
+
66.66%8/12100%0/033.33%1/360%6/10
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/lib/passport/index.html b/mission 10/coverage/lcov-report/src/lib/passport/index.html new file mode 100644 index 000000000..8a6dfa089 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/lib/passport/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for src/lib/passport + + + + + + + + + +
+
+

All files src/lib/passport

+
+ +
+ 87.87% + Statements + 29/33 +
+ + +
+ 83.33% + Branches + 5/6 +
+ + +
+ 75% + Functions + 3/4 +
+ + +
+ 87.87% + Lines + 29/33 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
100%7/7100%0/0100%0/0100%7/7
jwtStrategy.ts +
+
84.61%11/13100%2/266.66%2/384.61%11/13
localStrategy.ts +
+
84.61%11/1375%3/4100%1/184.61%11/13
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/lib/passport/index.ts.html b/mission 10/coverage/lcov-report/src/lib/passport/index.ts.html new file mode 100644 index 000000000..9d204e986 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/lib/passport/index.ts.html @@ -0,0 +1,112 @@ + + + + + + Code coverage report for src/lib/passport/index.ts + + + + + + + + + +
+
+

All files / src/lib/passport index.ts

+
+ +
+ 100% + Statements + 7/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 7/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +103x +3x +3x +  +3x +3x +3x +  +3x + 
import passport from 'passport';
+import { localStrategy } from './localStrategy';
+import { accessTokenStrategy, refreshTokenStrategy } from './jwtStrategy';
+ 
+passport.use('local', localStrategy);
+passport.use('access-token', accessTokenStrategy);
+passport.use('refresh-token', refreshTokenStrategy);
+ 
+export default passport;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/lib/passport/jwtStrategy.ts.html b/mission 10/coverage/lcov-report/src/lib/passport/jwtStrategy.ts.html new file mode 100644 index 000000000..5551ca2ac --- /dev/null +++ b/mission 10/coverage/lcov-report/src/lib/passport/jwtStrategy.ts.html @@ -0,0 +1,241 @@ + + + + + + Code coverage report for src/lib/passport/jwtStrategy.ts + + + + + + + + + +
+
+

All files / src/lib/passport jwtStrategy.ts

+
+ +
+ 84.61% + Statements + 11/13 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 66.66% + Functions + 2/3 +
+ + +
+ 84.61% + Lines + 11/13 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +533x +3x +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +4x +  +  +  +  +3x +  +  +  +  +  +4x +4x +  +  +4x +  +  +  +  +  +3x +  +  +  +  +3x +  +  +  + 
import { Strategy as JwtStrategy, ExtractJwt } from 'passport-jwt';
+import prisma from '../prisma';
+import type { Request } from 'express';
+import type { VerifiedCallback } from 'passport-jwt';
+import {
+  ACCESS_TOKEN_COOKIE_NAME,
+  REFRESH_TOKEN_COOKIE_NAME,
+  JWT_ACCESS_TOKEN_SECRET,
+  JWT_REFRESH_TOKEN_SECRET,
+} from '../constants';
+ 
+interface JwtPayload {
+  sub: number;
+}
+ 
+// const accessTokenOptions = {
+//   jwtFromRequest: (req: Request) => req.cookies[ACCESS_TOKEN_COOKIE_NAME],
+//   secretOrKey: JWT_ACCESS_TOKEN_SECRET,
+// };
+ 
+const accessTokenOptions = {
+  jwtFromRequest: (req: Request) => {
+    return req.cookies[ACCESS_TOKEN_COOKIE_NAME] || ExtractJwt.fromAuthHeaderAsBearerToken()(req);
+  },
+  secretOrKey: JWT_ACCESS_TOKEN_SECRET,
+};
+ 
+const refreshTokenOptions = {
+  jwtFromRequest: (req: Request) => req.cookies[REFRESH_TOKEN_COOKIE_NAME],
+  secretOrKey: JWT_REFRESH_TOKEN_SECRET,
+};
+ 
+async function jwtVerify(payload: JwtPayload, done: VerifiedCallback) {
+  try {
+    const user = await prisma.user.findUnique({
+      where: { id: payload.sub },
+    });
+    done(null, user);
+  } catch (error) {
+    done(error, false);
+  }
+}
+ 
+export const accessTokenStrategy = new JwtStrategy(
+  accessTokenOptions,
+  jwtVerify
+);
+ 
+export const refreshTokenStrategy = new JwtStrategy(
+  refreshTokenOptions,
+  jwtVerify
+);
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/lib/passport/localStrategy.ts.html b/mission 10/coverage/lcov-report/src/lib/passport/localStrategy.ts.html new file mode 100644 index 000000000..207cbfd94 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/lib/passport/localStrategy.ts.html @@ -0,0 +1,166 @@ + + + + + + Code coverage report for src/lib/passport/localStrategy.ts + + + + + + + + + +
+
+

All files / src/lib/passport localStrategy.ts

+
+ +
+ 84.61% + Statements + 11/13 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 84.61% + Lines + 11/13 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +283x +3x +3x +  +3x +  +  +  +  +  +4x +4x +4x +  +  +  +4x +4x +1x +  +  +3x +  +  +  +  +  + 
import { Strategy as LocalStrategy } from "passport-local";
+import bcrypt from "bcrypt";
+import prisma from "../prisma";
+ 
+export const localStrategy = new LocalStrategy(
+  {
+    usernameField: "email", // email을 localStrategy의 고정값 'username' 대신 쓰도록 지정
+    passwordField: "password",
+  },
+  async (email, password, done) => {
+    try {
+      const user = await prisma.user.findUnique({ where: { email } });
+      Iif (!user) {
+        return done(null, false, { message: "No user found" });
+      }
+ 
+      const isPasswordValid = await bcrypt.compare(password, user.password);
+      if (!isPasswordValid) {
+        return done(null, false, { message: "Invalid password" });
+      }
+ 
+      return done(null, user);
+    } catch (err) {
+      return done(err);
+    }
+  }
+);
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/lib/prisma.ts.html b/mission 10/coverage/lcov-report/src/lib/prisma.ts.html new file mode 100644 index 000000000..7a5882e44 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/lib/prisma.ts.html @@ -0,0 +1,97 @@ + + + + + + Code coverage report for src/lib/prisma.ts + + + + + + + + + +
+
+

All files / src/lib prisma.ts

+
+ +
+ 100% + Statements + 3/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 3/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +53x +  +3x +  +3x
import { PrismaClient } from '@prisma/client';
+ 
+const prisma = new PrismaClient();
+ 
+export default prisma;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/lib/token.ts.html b/mission 10/coverage/lcov-report/src/lib/token.ts.html new file mode 100644 index 000000000..d2e775f3e --- /dev/null +++ b/mission 10/coverage/lcov-report/src/lib/token.ts.html @@ -0,0 +1,166 @@ + + + + + + Code coverage report for src/lib/token.ts + + + + + + + + + +
+
+

All files / src/lib token.ts

+
+ +
+ 66.66% + Statements + 8/12 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 33.33% + Functions + 1/3 +
+ + +
+ 60% + Lines + 6/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +283x +3x +  +  +  +  +  +3x +  +  +3x +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +3x + 
 import jwt from 'jsonwebtoken';
+import {
+  JWT_ACCESS_TOKEN_SECRET,
+  JWT_REFRESH_TOKEN_SECRET,
+} from './constants';
+ 
+function generateTokens(userId: number) {
+  const accessToken = jwt.sign({ sub: userId }, JWT_ACCESS_TOKEN_SECRET, {
+    expiresIn: '1h',
+  });
+  const refreshToken = jwt.sign({ sub: userId }, JWT_REFRESH_TOKEN_SECRET, {
+    expiresIn: '1d',
+  });
+  return { accessToken, refreshToken };
+}
+ 
+function verifyAccessToken(token: string) {
+  const decoded = jwt.verify(token, JWT_ACCESS_TOKEN_SECRET);
+  return { userId: decoded.sub };
+}
+ 
+function verifyRefreshToken(token: string) {
+  const decoded = jwt.verify(token, JWT_REFRESH_TOKEN_SECRET);
+  return { userId: decoded.sub };
+}
+ 
+export { generateTokens, verifyAccessToken, verifyRefreshToken };
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/middlewares/errorHandler.ts.html b/mission 10/coverage/lcov-report/src/middlewares/errorHandler.ts.html new file mode 100644 index 000000000..050a6aa70 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/middlewares/errorHandler.ts.html @@ -0,0 +1,151 @@ + + + + + + Code coverage report for src/middlewares/errorHandler.ts + + + + + + + + + +
+
+

All files / src/middlewares errorHandler.ts

+
+ +
+ 33.33% + Statements + 3/9 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 33.33% + Lines + 3/9 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +233x +3x +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { z } from "zod";
+import httpStatus from "http-status";
+import express , { type Request, type Response, type NextFunction } from "express";
+ 
+interface ExtendedError extends Error {
+  code?: string;
+}
+ 
+export function errorHandler(err: ExtendedError, req: Request, res: Response, next: NextFunction) {
+  if (err instanceof z.ZodError) {
+    return res.status(httpStatus.BAD_REQUEST).json({ error: err.issues });
+  }
+ 
+  if (err.code === "P2025") {
+    return res.status(httpStatus.NOT_FOUND).json({ error: "Record not found" });
+  }
+ 
+  console.error("unhandled Error:", err);
+  return res
+    .status(httpStatus.INTERNAL_SERVER_ERROR)
+    .json({ error: "Internal Server Error" });
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/middlewares/index.html b/mission 10/coverage/lcov-report/src/middlewares/index.html new file mode 100644 index 000000000..3151fc189 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/middlewares/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/middlewares + + + + + + + + + +
+
+

All files src/middlewares

+
+ +
+ 33.33% + Statements + 3/9 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 33.33% + Lines + 3/9 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
errorHandler.ts +
+
33.33%3/90%0/40%0/133.33%3/9
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/repositories/alertRepository.ts.html b/mission 10/coverage/lcov-report/src/repositories/alertRepository.ts.html new file mode 100644 index 000000000..194d1210b --- /dev/null +++ b/mission 10/coverage/lcov-report/src/repositories/alertRepository.ts.html @@ -0,0 +1,184 @@ + + + + + + Code coverage report for src/repositories/alertRepository.ts + + + + + + + + + +
+
+

All files / src/repositories alertRepository.ts

+
+ +
+ 28.57% + Statements + 2/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/5 +
+ + +
+ 28.57% + Lines + 2/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +343x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import prisma from "../lib/prisma";
+ 
+export class AlertRepository {
+  async createAlert(data: { userId: number; message: string; link?: string }) {
+    return prisma.alert.create({ data });
+  }
+ 
+  async findByUserId(userId: number) {
+    return prisma.alert.findMany({
+      where: { userId },
+      orderBy: { createdAt: "desc" },
+    });
+  }
+ 
+  async markAsRead(id: number) {
+    return prisma.alert.update({
+      where: { id },
+      data: { isRead: true },
+    });
+  }
+ 
+  async countUnread(userId: number) {
+    return prisma.alert.count({
+      where: { userId, isRead: false },
+    });
+  }
+ 
+  async findById(id: number) {
+    return prisma.alert.findUnique({
+      where: { id },
+    });
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/repositories/articleRepository.ts.html b/mission 10/coverage/lcov-report/src/repositories/articleRepository.ts.html new file mode 100644 index 000000000..e71451e45 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/repositories/articleRepository.ts.html @@ -0,0 +1,199 @@ + + + + + + Code coverage report for src/repositories/articleRepository.ts + + + + + + + + + +
+
+

All files / src/repositories articleRepository.ts

+
+ +
+ 92.3% + Statements + 12/13 +
+ + +
+ 50% + Branches + 2/4 +
+ + +
+ 100% + Functions + 5/5 +
+ + +
+ 100% + Lines + 11/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +393x +  +  +3x +  +1x +  +  +  +1x +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +1x +1x +1x +  +1x +  +  +  +1x +  +  +  +3x
import prisma from "../lib/prisma";
+import { Prisma } from "@prisma/client";
+ 
+export class ArticleRepository {
+  async createArticle(data: { userId: number; title: string; content: string }) {
+    return prisma.article.create({ data });
+  }
+ 
+  async findMany(where: Prisma.ArticleWhereInput, skip: number, take: number) {
+    return prisma.article.findMany({
+      skip,
+      take,
+      orderBy: { createdAt: "desc" },
+      select: { id: true, title: true, content: true, createdAt: true },
+      where,
+    });
+  }
+ 
+  async findById(id: number) {
+    return prisma.article.findUnique({
+      where: { id },
+      select: { id: true, userId: true, title: true, content: true, createdAt: true },
+    });
+  }
+ 
+  async updatedArticle(id: number, data: { title?: string; content?: string }) {
+    const updateData: { title?: string; content?: string } = {};
+    Eif (data.title !== undefined) updateData.title = data.title;
+    Iif (data.content !== undefined) updateData.content = data.content;
+ 
+    return prisma.article.update({ where: { id }, data: updateData });
+  }
+ 
+  async deleteArticle(id: number): Promise<void> {
+    await prisma.article.delete({ where: { id } });
+  }
+}
+ 
+export default new ArticleRepository();
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/repositories/commentRepository.ts.html b/mission 10/coverage/lcov-report/src/repositories/commentRepository.ts.html new file mode 100644 index 000000000..aecec875f --- /dev/null +++ b/mission 10/coverage/lcov-report/src/repositories/commentRepository.ts.html @@ -0,0 +1,238 @@ + + + + + + Code coverage report for src/repositories/commentRepository.ts + + + + + + + + + +
+
+

All files / src/repositories commentRepository.ts

+
+ +
+ 30% + Statements + 3/10 +
+ + +
+ 0% + Branches + 0/8 +
+ + +
+ 0% + Functions + 0/7 +
+ + +
+ 30% + Lines + 3/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +523x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x
import prisma from "../lib/prisma";
+ 
+export class CommentRepository {
+  async createProductComment(userId: number, productId: number, content: string) {
+    return prisma.comment.create({
+      data: { content, productId, articleId: null, userId },
+    });
+  }
+ 
+  async createArticleComment(userId: number, articleId: number, content: string) {
+    return prisma.comment.create({
+      data: { content, productId: null, articleId, userId },
+    });
+  }
+ 
+  async findById(commentId: number) {
+    return prisma.comment.findUnique({ where: { id: commentId } });
+  }
+ 
+  async updateComment(commentId: number, content: string) {
+    return prisma.comment.update({
+      where: { id: commentId },
+      data: { content },
+    });
+  }
+ 
+  async deleteComment(commentId: number) {
+    return prisma.comment.delete({ where: { id: commentId } });
+  }
+ 
+  async findProductComments(productId: number, lastId?: number) {
+    return prisma.comment.findMany({
+      where: { articleId: null, productId },
+      take: 5,
+      skip: lastId ? 1 : 0,
+      ...(lastId && { cursor: { id: lastId } }),
+      select: { id: true, content: true, createdAt: true },
+    });
+  }
+ 
+  async findArticleComments(articleId: number, lastId?: number) {
+    return prisma.comment.findMany({
+      where: { articleId, productId: null },
+      take: 5,
+      skip: lastId ? 1 : 0,
+      ...(lastId && { cursor: { id: lastId } }),
+      select: { id: true, content: true, createdAt: true },
+    });
+  }
+}
+ 
+export default new CommentRepository();
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/repositories/index.html b/mission 10/coverage/lcov-report/src/repositories/index.html new file mode 100644 index 000000000..63e84a86c --- /dev/null +++ b/mission 10/coverage/lcov-report/src/repositories/index.html @@ -0,0 +1,191 @@ + + + + + + Code coverage report for src/repositories + + + + + + + + + +
+
+

All files src/repositories

+
+ +
+ 54.23% + Statements + 32/59 +
+ + +
+ 16.66% + Branches + 2/12 +
+ + +
+ 33.33% + Functions + 13/39 +
+ + +
+ 55.35% + Lines + 31/56 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
alertRepository.ts +
+
28.57%2/7100%0/00%0/528.57%2/7
articleRepository.ts +
+
92.3%12/1350%2/4100%5/5100%11/11
commentRepository.ts +
+
30%3/100%0/80%0/730%3/10
likeRepository.ts +
+
26.66%4/15100%0/08.33%1/1228.57%4/14
productRepository.ts +
+
100%7/7100%0/0100%5/5100%7/7
userRepository.ts +
+
57.14%4/7100%0/040%2/557.14%4/7
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/repositories/likeRepository.ts.html b/mission 10/coverage/lcov-report/src/repositories/likeRepository.ts.html new file mode 100644 index 000000000..834028ee0 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/repositories/likeRepository.ts.html @@ -0,0 +1,340 @@ + + + + + + Code coverage report for src/repositories/likeRepository.ts + + + + + + + + + +
+
+

All files / src/repositories likeRepository.ts

+
+ +
+ 26.66% + Statements + 4/15 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 8.33% + Functions + 1/12 +
+ + +
+ 28.57% + Lines + 4/14 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +863x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  + 
import prisma from "../lib/prisma";
+ 
+export class LikeRepository {
+  async findArticle(articleId: number) {
+    return prisma.article.findUnique({ where: { id: articleId } });
+  }
+ 
+  async findProduct(productId: number) {
+    return prisma.product.findUnique({ where: { id: productId } });
+  }
+ 
+  async findArticleLike(userId: number, articleId: number) {
+    return prisma.like.findUnique({
+      where: { userId_articleId: { userId, articleId } },
+    });
+  }
+ 
+  async findProductLike(userId: number, productId: number) {
+    return prisma.like.findUnique({
+      where: { userId_productId: { userId, productId } },
+    });
+  }
+ 
+  async toggleArticleLike(userId: number, articleId: number, current: boolean) {
+    return prisma.like.update({
+      where: { userId_articleId: { userId, articleId } },
+      data: { like: !current },
+    });
+  }
+ 
+  async toggleProductLike(userId: number, productId: number, current: boolean) {
+    return prisma.like.update({
+      where: { userId_productId: { userId, productId } },
+      data: { like: !current },
+    });
+  }
+ 
+  async createArticleLike(userId: number, articleId: number) {
+    return prisma.like.create({
+      data: { like: true, userId, articleId },
+    });
+  }
+ 
+  async createProductLike(userId: number, productId: number) {
+    return prisma.like.create({
+      data: { like: true, userId, productId },
+    });
+  }
+ 
+  async findLikedArticles(userId: number) {
+    return prisma.like.findMany({
+      where: { userId, articleId: { not: null }, like: true },
+      include: {
+        article: { select: { id: true, title: true } },
+      },
+    });
+  }
+ 
+  async findLikedProducts(userId: number) {
+    return prisma.like.findMany({
+      where: { userId, productId: { not: null }, like: true },
+      include: {
+        product: { select: { id: true, name: true, price: true, tags: true } },
+      },
+    });
+  }
+ 
+  async findUsersWhoLikedProduct(productId: number) {
+    const likes = await prisma.like.findMany({
+      where: {
+        productId,
+        like: true,
+      },
+      select: {
+        user: {
+          select: {
+            id: true,
+            nickname: true,
+          },
+        },
+      },
+    });
+    return likes.map((like) => like.user);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/repositories/productRepository.ts.html b/mission 10/coverage/lcov-report/src/repositories/productRepository.ts.html new file mode 100644 index 000000000..8d751a44c --- /dev/null +++ b/mission 10/coverage/lcov-report/src/repositories/productRepository.ts.html @@ -0,0 +1,229 @@ + + + + + + Code coverage report for src/repositories/productRepository.ts + + + + + + + + + +
+
+

All files / src/repositories productRepository.ts

+
+ +
+ 100% + Statements + 7/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 5/5 +
+ + +
+ 100% + Lines + 7/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +493x +  +  +  +3x +  +1x +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +1x +  + 
import prisma from "../lib/prisma";
+import { Prisma } from "@prisma/client";
+import { ProductCreateDTO, ProductUpdateDTO, ProductQueryDTO } from "../dtos/product.dto";
+ 
+export class ProductRepository {
+  async createProduct(data: { userId: number; name: string; description: string; price: number; tags: string }) {
+    return prisma.product.create({ data });
+  }
+ 
+  async findMany(where: Prisma.ProductWhereInput, skip: number, take: number) {
+    return prisma.product.findMany({
+      skip,
+      take,
+      orderBy: { createdAt: "desc" },
+      select: {
+        id: true,
+        name: true,
+        description: true,
+        price: true,
+        tags: true,
+        createdAt: true,
+      },
+      where,
+    });
+  }
+ 
+  async findById(id: number) {
+    return prisma.product.findUnique({
+      where: { id },
+      select: {
+        id: true,
+        userId: true,
+        name: true,
+        description: true,
+        price: true,
+        tags: true,
+        createdAt: true,
+      },
+    });
+  }
+ 
+  async updateProduct(id: number, data: Partial<{ name: string; description: string; price: number; tags: string }>) {
+    return prisma.product.update({ where: { id }, data });
+  }
+ 
+  async deleteProduct(id: number) {
+    return prisma.product.delete({ where: { id } });
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/repositories/userRepository.ts.html b/mission 10/coverage/lcov-report/src/repositories/userRepository.ts.html new file mode 100644 index 000000000..b7ca81b6a --- /dev/null +++ b/mission 10/coverage/lcov-report/src/repositories/userRepository.ts.html @@ -0,0 +1,169 @@ + + + + + + Code coverage report for src/repositories/userRepository.ts + + + + + + + + + +
+
+

All files / src/repositories userRepository.ts

+
+ +
+ 57.14% + Statements + 4/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 40% + Functions + 2/5 +
+ + +
+ 57.14% + Lines + 4/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +293x +  +3x +  +4x +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  + 
import prisma from "../lib/prisma";
+ 
+export class UserRepository {
+  async findByEmail(email: string) {
+    return prisma.user.findUnique({ where: { email } });
+  }
+ 
+  async findById(id: number) {
+    return prisma.user.findUnique({
+      where: { id },
+      select: { id: true, email: true, nickname: true, image: true, createdAt: true, updatedAt: true },
+    });
+  }
+ 
+  async createUser(email: string, nickname: string, password: string) {
+    return prisma.user.create({ data: { email, nickname, password } });
+  }
+ 
+  async updateUser(id: number, data: Partial<{ nickname: string; image: string; password: string }>) {
+    return prisma.user.update({ where: { id }, data });
+  }
+ 
+  async findProductsByUserId(userId: number) {
+    return prisma.product.findMany({
+      where: { userId },
+      select: { name: true, description: true, price: true, tags: true },
+    });
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/routers/alertRouter.ts.html b/mission 10/coverage/lcov-report/src/routers/alertRouter.ts.html new file mode 100644 index 000000000..04aaa0c04 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/routers/alertRouter.ts.html @@ -0,0 +1,121 @@ + + + + + + Code coverage report for src/routers/alertRouter.ts + + + + + + + + + +
+
+

All files / src/routers alertRouter.ts

+
+ +
+ 100% + Statements + 8/8 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 8/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +133x +3x +3x +  +3x +3x +  +3x +  +3x +  +3x + 
import express from "express";
+import passport from "../lib/passport";
+import { AlertController } from "../controllers/alertController";
+ 
+const router = express.Router();
+const controller = new AlertController();
+ 
+router.get("/", passport.authenticate("access-token", { session: false }), controller.list);
+ 
+router.patch("/:id/read", passport.authenticate("access-token", { session: false }), controller.markAsRead);
+ 
+export default router;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/routers/articleRouter.ts.html b/mission 10/coverage/lcov-report/src/routers/articleRouter.ts.html new file mode 100644 index 000000000..eaff460e0 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/routers/articleRouter.ts.html @@ -0,0 +1,130 @@ + + + + + + Code coverage report for src/routers/articleRouter.ts + + + + + + + + + +
+
+

All files / src/routers articleRouter.ts

+
+ +
+ 100% + Statements + 11/11 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 11/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +163x +3x +3x +  +3x +3x +  +3x +3x +3x +  +3x +3x +  +3x + 
import express from "express";
+import passport from "../lib/passport";
+import { ArticleController } from "../controllers/articleController";
+ 
+const router = express.Router();
+const controller = new ArticleController();
+ 
+router.post("/", passport.authenticate("access-token", { session: false }), controller.create);
+router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update);
+router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete);
+ 
+router.get("/", controller.list);
+router.get("/:id", controller.detail);
+ 
+export default router;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/routers/commentRouter.ts.html b/mission 10/coverage/lcov-report/src/routers/commentRouter.ts.html new file mode 100644 index 000000000..a151f3f54 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/routers/commentRouter.ts.html @@ -0,0 +1,133 @@ + + + + + + Code coverage report for src/routers/commentRouter.ts + + + + + + + + + +
+
+

All files / src/routers commentRouter.ts

+
+ +
+ 100% + Statements + 12/12 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 12/12 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +173x +3x +3x +  +3x +3x +  +3x +3x +3x +3x +  +3x +3x +  +3x + 
import express from "express";
+import passport from "../lib/passport";
+import { CommentController } from "../controllers/commentController";
+ 
+const router = express.Router();
+const controller = new CommentController();
+ 
+router.post("/products/:id", passport.authenticate("access-token", { session: false }), controller.createProductComment);
+router.post("/articles/:id", passport.authenticate("access-token", { session: false }), controller.createArticleComment);
+router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.modifyComment);
+router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.deleteComment);
+ 
+router.get("/products/:id", controller.productCommentList);
+router.get("/articles/:id", controller.articleCommentList);
+ 
+export default router;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/routers/index.html b/mission 10/coverage/lcov-report/src/routers/index.html new file mode 100644 index 000000000..7de3d7a42 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/routers/index.html @@ -0,0 +1,221 @@ + + + + + + Code coverage report for src/routers + + + + + + + + + +
+
+

All files src/routers

+
+ +
+ 98.98% + Statements + 98/99 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 98/98 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
alertRouter.ts +
+
100%8/8100%0/0100%0/0100%8/8
articleRouter.ts +
+
100%11/11100%0/0100%0/0100%11/11
commentRouter.ts +
+
100%12/12100%0/0100%0/0100%12/12
index.ts +
+
100%17/17100%0/0100%0/0100%17/17
likeRouter.ts +
+
100%10/10100%0/0100%0/0100%10/10
photoRouter.ts +
+
100%9/9100%0/0100%0/0100%9/9
productRouter.ts +
+
100%11/11100%0/0100%0/0100%11/11
userRouter.ts +
+
95.23%20/2175%3/4100%2/2100%20/20
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/routers/index.ts.html b/mission 10/coverage/lcov-report/src/routers/index.ts.html new file mode 100644 index 000000000..e7a44af4e --- /dev/null +++ b/mission 10/coverage/lcov-report/src/routers/index.ts.html @@ -0,0 +1,145 @@ + + + + + + Code coverage report for src/routers/index.ts + + + + + + + + + +
+
+

All files / src/routers index.ts

+
+ +
+ 100% + Statements + 17/17 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 17/17 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +213x +  +3x +3x +3x +3x +3x +3x +3x +  +3x +  +3x +3x +3x +3x +3x +3x +3x +  +3x
import express from "express";
+ 
+import userRouter from "./userRouter";
+import articleRouter from "./articleRouter";
+import productRouter from "./productRouter";
+import commentRouter from "./commentRouter";
+import likeRouter from "./likeRouter";
+import photoRouter from "./photoRouter";
+import alertRouter from "./alertRouter";
+ 
+const router = express.Router();
+ 
+router.use("/users", userRouter);
+router.use("/articles", articleRouter);
+router.use("/products", productRouter);
+router.use("/comments", commentRouter);
+router.use("/likes", likeRouter);
+router.use(photoRouter); 
+router.use("/alerts", alertRouter);
+ 
+export default router;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/routers/likeRouter.ts.html b/mission 10/coverage/lcov-report/src/routers/likeRouter.ts.html new file mode 100644 index 000000000..444f2b2bf --- /dev/null +++ b/mission 10/coverage/lcov-report/src/routers/likeRouter.ts.html @@ -0,0 +1,121 @@ + + + + + + Code coverage report for src/routers/likeRouter.ts + + + + + + + + + +
+
+

All files / src/routers likeRouter.ts

+
+ +
+ 100% + Statements + 10/10 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 10/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +133x +3x +3x +  +3x +3x +  +3x +3x +3x +3x +  +3x
import express from "express";
+import passport from "../lib/passport";
+import { LikeController } from "../controllers/likeController";
+ 
+const router = express.Router();
+const controller = new LikeController();
+ 
+router.post("/articles/:id", passport.authenticate("access-token", { session: false }), controller.likeArticle);
+router.post("/products/:id", passport.authenticate("access-token", { session: false }), controller.likeProduct);
+router.get("/articles", passport.authenticate("access-token", { session: false }), controller.getLikedArticles);
+router.get("/products", passport.authenticate("access-token", { session: false }), controller.getLikedProducts);
+ 
+export default router;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/routers/photoRouter.ts.html b/mission 10/coverage/lcov-report/src/routers/photoRouter.ts.html new file mode 100644 index 000000000..2865161c5 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/routers/photoRouter.ts.html @@ -0,0 +1,136 @@ + + + + + + Code coverage report for src/routers/photoRouter.ts + + + + + + + + + +
+
+

All files / src/routers photoRouter.ts

+
+ +
+ 100% + Statements + 9/9 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 9/9 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +183x +3x +3x +3x +  +3x +3x +3x +  +3x +  +  +  +  +  +  +3x + 
import express from "express";
+import multer from "multer";
+import passport from "../lib/passport";
+import { PhotoController } from "../controllers/photoController";
+ 
+const router = express.Router();
+const upload = multer({ dest: "uploads/" });
+const controller = new PhotoController();
+ 
+router.post(
+  "/",
+  passport.authenticate("access-token", { session: false }),
+  upload.single("image"),
+  controller.upload
+);
+ 
+export default router;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/routers/productRouter.ts.html b/mission 10/coverage/lcov-report/src/routers/productRouter.ts.html new file mode 100644 index 000000000..863712331 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/routers/productRouter.ts.html @@ -0,0 +1,136 @@ + + + + + + Code coverage report for src/routers/productRouter.ts + + + + + + + + + +
+
+

All files / src/routers productRouter.ts

+
+ +
+ 100% + Statements + 11/11 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 11/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +183x +3x +3x +  +3x +3x +  +  +3x +3x +3x +  +  +3x +3x +  +3x + 
import express from "express";
+import passport from "../lib/passport";
+import { ProductController } from "../controllers/productController";
+ 
+const router = express.Router();
+const controller = new ProductController();
+ 
+// ✅ 인증 필요
+router.post("/", passport.authenticate("access-token", { session: false }), controller.create);
+router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update);
+router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete);
+ 
+// ✅ 인증 필요 X (공개)
+router.get("/", controller.list);
+router.get("/:id", controller.detail);
+ 
+export default router;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/routers/userRouter.ts.html b/mission 10/coverage/lcov-report/src/routers/userRouter.ts.html new file mode 100644 index 000000000..c35373b14 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/routers/userRouter.ts.html @@ -0,0 +1,274 @@ + + + + + + Code coverage report for src/routers/userRouter.ts + + + + + + + + + +
+
+

All files / src/routers userRouter.ts

+
+ +
+ 95.23% + Statements + 20/21 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 20/20 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +643x +3x +3x +  +3x +3x +  +3x +3x +  +  +4x +  +  +  +  +  +  +  +4x +  +4x +1x +  +  +  +  +3x +3x +  +  +  +  +  +  +3x +  +  +  +  +3x +  +  +  +  +3x +  +  +  +  +3x +  +  +  +  +3x +  +  +  +  +3x +  +3x + 
import express from "express";
+import passport from "../lib/passport";
+import { UserController } from "../controllers/userController";
+ 
+const router = express.Router();
+const controller = new UserController();
+ 
+router.post("/register", controller.register);
+router.post(
+  "/login",
+  (req, res, next) => {
+    passport.authenticate(
+      "local",
+      { session: false },
+      (
+        err: any,
+        user: Express.User | false,
+        info: { message?: string } | undefined
+      ) => {
+        Iif (err) return next(err);
+ 
+        if (!user) {
+          return res.status(401).json({
+            message: "Unauthorized", 
+          });
+        }
+ 
+        req.user = user;
+        next();
+      }
+    )(req, res, next);
+  },
+  controller.login
+);
+ 
+router.get(
+  "/profile",
+  passport.authenticate("access-token", { session: false }),
+  controller.profile
+);
+router.patch(
+  "/modifyInformation",
+  passport.authenticate("access-token", { session: false }),
+  controller.modifyInformation
+);
+router.patch(
+  "/modifyPassword",
+  passport.authenticate("access-token", { session: false }),
+  controller.modifyPassword
+);
+router.get(
+  "/products",
+  passport.authenticate("access-token", { session: false }),
+  controller.products
+);
+router.post(
+  "/refresh",
+  passport.authenticate("refresh-token", { session: false }),
+  controller.refreshTokens
+);
+router.post("/logout", controller.logout);
+ 
+export default router;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/services/alertService.ts.html b/mission 10/coverage/lcov-report/src/services/alertService.ts.html new file mode 100644 index 000000000..32e6e0b78 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/services/alertService.ts.html @@ -0,0 +1,196 @@ + + + + + + Code coverage report for src/services/alertService.ts + + + + + + + + + +
+
+

All files / src/services alertService.ts

+
+ +
+ 23.52% + Statements + 4/17 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 20% + Functions + 1/5 +
+ + +
+ 25% + Lines + 4/16 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +383x +3x +  +3x +9x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { AlertRepository } from "../repositories/alertRepository";
+import { getIo } from "../socket/io";
+ 
+export class AlertService {
+  private repo = new AlertRepository();
+ 
+  async create(userId: number, message: string, link?: string) {
+    const alert = await this.repo.createAlert({ userId, message, link });
+ 
+    const io = getIo();
+    io.to(`user:${userId}`).emit("newAlert", alert);
+ 
+    return alert;
+  }
+ 
+  async list(userId: number) {
+    return this.repo.findByUserId(userId);
+  }
+ 
+  async read(alertId: number, userId: number) {
+    const alert = await this.repo.findById(alertId);
+ 
+    if (!alert) return false;
+ 
+    if (alert.userId !== userId) {
+      return false;
+    }
+ 
+    await this.repo.markAsRead(alertId);
+ 
+    return true;
+  }
+ 
+  async countUnread(userId: number) {
+    return this.repo.countUnread(userId);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/services/articleService.ts.html b/mission 10/coverage/lcov-report/src/services/articleService.ts.html new file mode 100644 index 000000000..5f596d81e --- /dev/null +++ b/mission 10/coverage/lcov-report/src/services/articleService.ts.html @@ -0,0 +1,220 @@ + + + + + + Code coverage report for src/services/articleService.ts + + + + + + + + + +
+
+

All files / src/services articleService.ts

+
+ +
+ 75% + Statements + 15/20 +
+ + +
+ 50% + Branches + 5/10 +
+ + +
+ 83.33% + Functions + 5/6 +
+ + +
+ 93.75% + Lines + 15/16 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +463x +  +  +  +3x +6x +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +1x +  +  +  +2x +  +  +  +1x +1x +1x +  +1x +  +  +  +1x +1x +1x +  +1x +  +  +  +3x
import { ArticleRepository } from "../repositories/articleRepository";
+import type { ArticleCreateDTO, ArticleUpdateDTO, ArticleQueryDTO } from "../dtos/article.dto";
+import type { Prisma } from "@prisma/client";
+ 
+export class ArticleService {
+  private repo = new ArticleRepository();
+ 
+  async create(userId: number, data: ArticleCreateDTO) {
+    return this.repo.createArticle({ ...data, userId });
+  }
+ 
+  async list({ page, pageSize, keyword }: ArticleQueryDTO) {
+    const where: Prisma.ArticleWhereInput = keyword
+      ? {
+          OR: [
+            { title: { contains: keyword, mode: "insensitive" } },
+            { content: { contains: keyword, mode: "insensitive" } },
+          ],
+        }
+      : {};
+ 
+    return this.repo.findMany(where, (page - 1) * pageSize, pageSize);
+  }
+ 
+  async getDetail(id: number) {
+    return this.repo.findById(id);
+  }
+ 
+  async update(userId: number, data: ArticleUpdateDTO, articleId: number) {
+    const article = await this.repo.findById(articleId);
+    Iif (!article) throw new Error("NOT_FOUND");
+    Iif (article.userId !== userId) throw new Error("FORBIDDEN");
+ 
+    return this.repo.updatedArticle(articleId, data);
+  }
+ 
+  async delete(userId: number, articleId: number) {
+    const article = await this.repo.findById(articleId);
+    Iif (!article) throw new Error("NOT_FOUND");
+    Iif (article.userId !== userId) throw new Error("FORBIDDEN");
+ 
+    await this.repo.deleteArticle(articleId);
+  }
+}
+ 
+export default new ArticleService();
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/services/commentService.ts.html b/mission 10/coverage/lcov-report/src/services/commentService.ts.html new file mode 100644 index 000000000..9aa0aa0ae --- /dev/null +++ b/mission 10/coverage/lcov-report/src/services/commentService.ts.html @@ -0,0 +1,346 @@ + + + + + + Code coverage report for src/services/commentService.ts + + + + + + + + + +
+
+

All files / src/services commentService.ts

+
+ +
+ 24.32% + Statements + 9/37 +
+ + +
+ 0% + Branches + 0/20 +
+ + +
+ 14.28% + Functions + 1/7 +
+ + +
+ 27.27% + Lines + 9/33 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +883x +3x +3x +3x +  +3x +3x +3x +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { CommentRepository } from "../repositories/commentRepository";
+import { ArticleRepository } from "../repositories/articleRepository";
+import { ProductRepository } from "../repositories/productRepository";
+import { AlertService } from "../services/alertService";
+ 
+export class CommentService {
+  private repo = new CommentRepository();
+  private articleRepo = new ArticleRepository();
+  private productRepo = new ProductRepository();
+  private alertService = new AlertService();
+ 
+  async createArticleComment(
+    userId: number,
+    articleId: number,
+    content: string
+  ) {
+    const article = await this.articleRepo.findById(articleId);
+    if (!article) {
+      throw new Error("Article not found");
+    }
+ 
+    const comment = await this.repo.createArticleComment(
+      userId,
+      articleId,
+      content
+    );
+ 
+    if (article && article.userId !== userId) {
+      await this.alertService.create(
+        article.userId,
+        "내 게시글에 새로운 댓글이 달렸습니다.",
+        `/articles/${articleId}`
+      );
+    }
+ 
+    return comment;
+  }
+ 
+  async createProductComment(
+    userId: number,
+    productId: number,
+    content: string
+  ) {
+    const product = await this.productRepo.findById(productId);
+    if (!product) {
+      throw new Error("Product not found");
+    }
+ 
+    const comment = await this.repo.createProductComment(
+      userId,
+      productId,
+      content
+    );
+ 
+    if (product && product.userId !== userId) {
+      await this.alertService.create(
+        product.userId,
+        "내 판매글에 새로운 댓글이 달렸습니다.",
+        `/products/${productId}`
+      );
+    }
+ 
+    return comment;
+  }
+ 
+  async updateComment(userId: number, commentId: number, content: string) {
+    const comment = await this.repo.findById(commentId);
+    if (!comment) throw new Error("NOT_FOUND");
+    if (comment.userId !== userId) throw new Error("FORBIDDEN");
+    return this.repo.updateComment(commentId, content);
+  }
+ 
+  async deleteComment(userId: number, commentId: number) {
+    const comment = await this.repo.findById(commentId);
+    if (!comment) throw new Error("NOT_FOUND");
+    if (comment.userId !== userId) throw new Error("FORBIDDEN");
+    await this.repo.deleteComment(commentId);
+  }
+ 
+  async getProductComments(productId: number, lastId?: number) {
+    return this.repo.findProductComments(productId, lastId);
+  }
+ 
+  async getArticleComments(articleId: number, lastId?: number) {
+    return this.repo.findArticleComments(articleId, lastId);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/services/index.html b/mission 10/coverage/lcov-report/src/services/index.html new file mode 100644 index 000000000..2705c346d --- /dev/null +++ b/mission 10/coverage/lcov-report/src/services/index.html @@ -0,0 +1,191 @@ + + + + + + Code coverage report for src/services + + + + + + + + + +
+
+

All files src/services

+
+ +
+ 45.03% + Statements + 68/151 +
+ + +
+ 23.43% + Branches + 15/64 +
+ + +
+ 43.24% + Functions + 16/37 +
+ + +
+ 51.14% + Lines + 67/131 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
alertService.ts +
+
23.52%4/170%0/420%1/525%4/16
articleService.ts +
+
75%15/2050%5/1083.33%5/693.75%15/16
commentService.ts +
+
24.32%9/370%0/2014.28%1/727.27%9/33
likeService.ts +
+
15.78%3/190%0/820%1/517.64%3/17
productService.ts +
+
77.41%24/3157.14%8/1471.42%5/792.3%24/26
userService.ts +
+
48.14%13/2725%2/842.85%3/752.17%12/23
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/services/likeService.ts.html b/mission 10/coverage/lcov-report/src/services/likeService.ts.html new file mode 100644 index 000000000..78a992242 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/services/likeService.ts.html @@ -0,0 +1,187 @@ + + + + + + Code coverage report for src/services/likeService.ts + + + + + + + + + +
+
+

All files / src/services likeService.ts

+
+ +
+ 15.78% + Statements + 3/19 +
+ + +
+ 0% + Branches + 0/8 +
+ + +
+ 20% + Functions + 1/5 +
+ + +
+ 17.64% + Lines + 3/17 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +353x +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { LikeRepository } from "../repositories/likeRepository";
+ 
+export class LikeService {
+  private repo = new LikeRepository();
+ 
+  async likeArticle(userId: number, articleId: number) {
+    const article = await this.repo.findArticle(articleId);
+    if (!article) throw new Error("ARTICLE_NOT_FOUND");
+ 
+    const existing = await this.repo.findArticleLike(userId, articleId);
+    if (existing) {
+      return this.repo.toggleArticleLike(userId, articleId, existing.like);
+    }
+    return this.repo.createArticleLike(userId, articleId);
+  }
+ 
+  async likeProduct(userId: number, productId: number) {
+    const product = await this.repo.findProduct(productId);
+    if (!product) throw new Error("PRODUCT_NOT_FOUND");
+ 
+    const existing = await this.repo.findProductLike(userId, productId);
+    if (existing) {
+      return this.repo.toggleProductLike(userId, productId, existing.like);
+    }
+    return this.repo.createProductLike(userId, productId);
+  }
+ 
+  async getLikedArticles(userId: number) {
+    return this.repo.findLikedArticles(userId);
+  }
+ 
+  async getLikedProducts(userId: number) {
+    return this.repo.findLikedProducts(userId);
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/services/productService.ts.html b/mission 10/coverage/lcov-report/src/services/productService.ts.html new file mode 100644 index 000000000..5d40c2398 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/services/productService.ts.html @@ -0,0 +1,289 @@ + + + + + + Code coverage report for src/services/productService.ts + + + + + + + + + +
+
+

All files / src/services productService.ts

+
+ +
+ 77.41% + Statements + 24/31 +
+ + +
+ 57.14% + Branches + 8/14 +
+ + +
+ 71.42% + Functions + 5/7 +
+ + +
+ 92.3% + Lines + 24/26 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +693x +3x +3x +  +  +  +3x +3x +3x +3x +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +1x +  +  +  +2x +  +  +  +  +  +  +  +1x +1x +1x +  +1x +1x +  +1x +1x +  +1x +  +1x +  +  +  +  +  +  +  +  +1x +  +  +  +1x +1x +1x +  +1x +  +  + 
import { ProductRepository } from "../repositories/productRepository";
+import { LikeRepository } from "../repositories/likeRepository";
+import { AlertService } from "../services/alertService";
+import type { ProductCreateDTO, ProductQueryDTO } from "../dtos/product.dto";
+import type { Prisma } from "@prisma/client";
+ 
+export class ProductService {
+  private repo = new ProductRepository();
+  private likeRepo = new LikeRepository();
+  private alertService = new AlertService();
+ 
+  async create(userId: number, data: ProductCreateDTO) {
+    return this.repo.createProduct({ ...data, userId });
+  }
+ 
+  async list({ page, pageSize, keyword }: ProductQueryDTO) {
+    const where: Prisma.ProductWhereInput = keyword
+      ? {
+          OR: [
+            { name: { contains: keyword, mode: "insensitive" } },
+            { description: { contains: keyword, mode: "insensitive" } },
+          ],
+        }
+      : {};
+    return this.repo.findMany(where, (page - 1) * pageSize, pageSize);
+  }
+ 
+  async getDetail(id: number) {
+    return this.repo.findById(id);
+  }
+ 
+  async update(
+    userId: number,
+    productId: number,
+    data: { name?: string; description?: string; price?: number; tags?: string }
+  ) {
+    const product = await this.repo.findById(productId);
+    Iif (!product) throw new Error("NOT_FOUND");
+    Iif (product.userId !== userId) throw new Error("FORBIDDEN");
+ 
+    const oldPrice = product.price;
+    const updated = await this.repo.updateProduct(productId, data);
+ 
+    Eif (data.price !== undefined && data.price !== oldPrice) {
+      const likedUsers = await this.likeRepo.findUsersWhoLikedProduct(productId);
+      
+      const targetUsers = likedUsers.filter((u) => u.id !== userId);
+ 
+      for (const user of targetUsers) {
+        await this.alertService.create(
+          user.id,
+          `좋아요한 상품 "${updated.name}"의 가격이 ${oldPrice}원 → ${data.price}원으로 변경되었습니다.`,
+          `/products/${productId}`
+        );
+      }
+    }
+ 
+    return updated;
+  }
+ 
+  async delete(userId: number, productId: number) {
+    const product = await this.repo.findById(productId);
+    Iif (!product) throw new Error("NOT_FOUND");
+    Iif (product.userId !== userId) throw new Error("FORBIDDEN");
+ 
+    await this.repo.deleteProduct(productId);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/services/userService.ts.html b/mission 10/coverage/lcov-report/src/services/userService.ts.html new file mode 100644 index 000000000..e7a8fe2ef --- /dev/null +++ b/mission 10/coverage/lcov-report/src/services/userService.ts.html @@ -0,0 +1,229 @@ + + + + + + Code coverage report for src/services/userService.ts + + + + + + + + + +
+
+

All files / src/services userService.ts

+
+ +
+ 48.14% + Statements + 13/27 +
+ + +
+ 25% + Branches + 2/8 +
+ + +
+ 42.85% + Functions + 3/7 +
+ + +
+ 52.17% + Lines + 12/23 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +493x +3x +3x +  +  +3x +3x +  +  +2x +2x +  +1x +1x +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  + 
import bcrypt from "bcrypt";
+import { UserRepository } from "../repositories/userRepository";
+import { generateTokens } from "../lib/token";
+import type { UserRegisterDTO, UserUpdateDTO, UserPasswordDTO } from "../dtos/user.dto";
+ 
+export class UserService {
+  private userRepo = new UserRepository();
+ 
+  async register(data: UserRegisterDTO) {
+    const exists = await this.userRepo.findByEmail(data.email);
+    if (exists) throw new Error("EMAIL_EXISTS");
+ 
+    const salt = await bcrypt.genSalt(10);
+    const hashedPassword = await bcrypt.hash(data.password, salt);
+ 
+    await this.userRepo.createUser(data.email, data.nickname, hashedPassword);
+    return { message: "User registered successfully" };
+  }
+ 
+  async getProfile(userId: number) {
+    return this.userRepo.findById(userId);
+  }
+ 
+  async updateInformation(userId: number, nickname?: string, image?: string) {
+    const updateData: Record<string, string> = {};
+    if (nickname) updateData.nickname = nickname;
+    if (image) updateData.image = image;
+ 
+    if (Object.keys(updateData).length === 0) throw new Error("NO_DATA");
+ 
+    return this.userRepo.updateUser(userId, updateData);
+  }
+ 
+  async updatePassword(userId: number, data: UserPasswordDTO) {
+    const salt = await bcrypt.genSalt(10);
+    const hashedPassword = await bcrypt.hash(data.password, salt);
+    await this.userRepo.updateUser(userId, { password: hashedPassword });
+    return { message: "Password updated successfully" };
+  }
+ 
+  async getProducts(userId: number) {
+    return this.userRepo.findProductsByUserId(userId);
+  }
+ 
+  generateUserTokens(userId: number) {
+    return generateTokens(userId);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/socket.ts.html b/mission 10/coverage/lcov-report/src/socket.ts.html new file mode 100644 index 000000000..93f1da548 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/socket.ts.html @@ -0,0 +1,130 @@ + + + + + + Code coverage report for src/socket.ts + + + + + + + + + +
+
+

All files / src socket.ts

+
+ +
+ 25% + Statements + 2/8 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 25% + Functions + 1/4 +
+ + +
+ 25% + Lines + 2/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16  +  +5x +5x +  +  +  +  +  +  +  +  +  +  +  + 
import { Server } from "socket.io";
+ 
+export function registerSocket(io: Server) {
+    io.on("connection", (socket) => {
+        console.log("New client connected:", socket.id);
+ 
+        socket.on("register", (userId: number) => {
+            socket.join(`user:${userId}`);
+            console.log(`User ${userId} joined room user:${userId}`);
+        });
+ 
+        socket.on("disconnect", () => {
+            console.log("Client disconnected:", socket.id);
+        });
+    });
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/socket/index.html b/mission 10/coverage/lcov-report/src/socket/index.html new file mode 100644 index 000000000..a4f987062 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/socket/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/socket + + + + + + + + + +
+
+

All files src/socket

+
+ +
+ 59.09% + Statements + 13/22 +
+ + +
+ 25% + Branches + 1/4 +
+ + +
+ 75% + Functions + 3/4 +
+ + +
+ 61.9% + Lines + 13/21 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
io.ts +
+
88.88%8/950%1/2100%2/288.88%8/9
socket.ts +
+
38.46%5/130%0/250%1/241.66%5/12
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/socket/io.ts.html b/mission 10/coverage/lcov-report/src/socket/io.ts.html new file mode 100644 index 000000000..6e044e264 --- /dev/null +++ b/mission 10/coverage/lcov-report/src/socket/io.ts.html @@ -0,0 +1,145 @@ + + + + + + Code coverage report for src/socket/io.ts + + + + + + + + + +
+
+

All files / src/socket io.ts

+
+ +
+ 88.88% + Statements + 8/9 +
+ + +
+ 50% + Branches + 1/2 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 88.88% + Lines + 8/9 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +213x +  +3x +  +3x +3x +  +  +  +  +  +3x +  +  +3x +3x +  +  +3x +  + 
import { Server } from "socket.io";
+ 
+let io: Server | null = null;
+ 
+export function initIo(server: any) {
+  io = new Server(server, {
+    cors: {
+      origin: "http://localhost:3000",
+      methods: ["GET", "POST"],
+    },
+  });
+  return io;
+}
+ 
+export function getIo(): Server {
+  Iif (!io) {
+    throw new Error("Socket.io has not been initialized!");
+  }
+  return io;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/src/socket/socket.ts.html b/mission 10/coverage/lcov-report/src/socket/socket.ts.html new file mode 100644 index 000000000..070fa8adf --- /dev/null +++ b/mission 10/coverage/lcov-report/src/socket/socket.ts.html @@ -0,0 +1,154 @@ + + + + + + Code coverage report for src/socket/socket.ts + + + + + + + + + +
+
+

All files / src/socket socket.ts

+
+ +
+ 38.46% + Statements + 5/13 +
+ + +
+ 0% + Branches + 0/2 +
+ + +
+ 50% + Functions + 1/2 +
+ + +
+ 41.66% + Lines + 5/12 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +243x +3x +  +3x +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { getIo } from "./io";
+import jwt from "jsonwebtoken";
+ 
+export function registerSocket() {
+  const io = getIo(); // <-- initIo에서 만든 io 가져오기
+ 
+  io.on("connection", (socket) => {
+    console.log("Socket connected:", socket.id);
+ 
+    const token = socket.handshake.auth?.token;
+    if (!token) return socket.disconnect();
+ 
+    try {
+      const decoded = jwt.verify(token, process.env.JWT_SECRET!) as {
+        id: number;
+      };
+ 
+      socket.join(`user:${decoded.id}`);
+    } catch (err) {
+      socket.disconnect();
+    }
+  });
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/test/helpers/authHelper.ts.html b/mission 10/coverage/lcov-report/test/helpers/authHelper.ts.html new file mode 100644 index 000000000..c5cd6b345 --- /dev/null +++ b/mission 10/coverage/lcov-report/test/helpers/authHelper.ts.html @@ -0,0 +1,154 @@ + + + + + + Code coverage report for test/helpers/authHelper.ts + + + + + + + + + +
+
+

All files / test/helpers authHelper.ts

+
+ +
+ 100% + Statements + 7/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 7/7 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24  +4x +4x +  +4x +  +4x +  +  +  +  +4x +  +  +  +4x +  +4x +  +  +  +  +  + 
// ✅ test/helpers/authHelper.ts
+import supertest from "supertest";
+import app from "../../src/app";
+ 
+export const authHelper = {
+  async registerAndLogin() {
+    const userData = {
+      email: `test_${Date.now()}@test.com`,
+      password: "1234",
+      nickname: `nick_${Date.now()}`,
+    };
+    const registerRes = await supertest(app)
+      .post("/users/register")
+      .send(userData);
+ 
+    const loginRes = await supertest(app).post("/users/login").send(userData);
+ 
+    return {
+      token: loginRes.body.token,
+      user: loginRes.body.user, // <- 반드시 user 포함
+    };
+  },
+};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/test/helpers/index.html b/mission 10/coverage/lcov-report/test/helpers/index.html new file mode 100644 index 000000000..d98ac9d79 --- /dev/null +++ b/mission 10/coverage/lcov-report/test/helpers/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for test/helpers + + + + + + + + + +
+
+

All files test/helpers

+
+ +
+ 100% + Statements + 14/14 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 13/13 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
authHelper.ts +
+
100%7/7100%0/0100%1/1100%7/7
resetDatabase.ts +
+
100%7/7100%2/2100%1/1100%6/6
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/test/helpers/resetDatabase.ts.html b/mission 10/coverage/lcov-report/test/helpers/resetDatabase.ts.html new file mode 100644 index 000000000..e853802cc --- /dev/null +++ b/mission 10/coverage/lcov-report/test/helpers/resetDatabase.ts.html @@ -0,0 +1,124 @@ + + + + + + Code coverage report for test/helpers/resetDatabase.ts + + + + + + + + + +
+
+

All files / test/helpers resetDatabase.ts

+
+ +
+ 100% + Statements + 7/7 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 6/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +145x +  +5x +5x +  +  +  +5x +35x +30x +  +  +  + 
import prisma from "../../src/lib/prisma";
+ 
+export const resetDatabase = async () => {
+  const tablenames = await prisma.$queryRaw<
+    { tablename: string }[]
+  >`SELECT tablename FROM pg_tables WHERE schemaname='public'`;
+ 
+  for (const { tablename } of tablenames) {
+    if (tablename !== "_prisma_migrations") {
+      await prisma.$executeRawUnsafe(`TRUNCATE TABLE "${tablename}" RESTART IDENTITY CASCADE;`);
+    }
+  }
+};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/test/index.html b/mission 10/coverage/lcov-report/test/index.html new file mode 100644 index 000000000..d32cebf70 --- /dev/null +++ b/mission 10/coverage/lcov-report/test/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for test + + + + + + + + + +
+
+

All files test

+
+ +
+ 100% + Statements + 20/20 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 19/19 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
setup.ts +
+
100%9/9100%0/0100%1/1100%8/8
utils.ts +
+
100%11/11100%0/0100%1/1100%11/11
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/test/setup.ts.html b/mission 10/coverage/lcov-report/test/setup.ts.html new file mode 100644 index 000000000..770d8324b --- /dev/null +++ b/mission 10/coverage/lcov-report/test/setup.ts.html @@ -0,0 +1,118 @@ + + + + + + Code coverage report for test/setup.ts + + + + + + + + + +
+
+

All files / test setup.ts

+
+ +
+ 100% + Statements + 9/9 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 8/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +123x +  +  +3x +3x +3x +3x +3x +3x +3x +  + 
import prisma from "../src/lib/prisma";
+ 
+// 테스트 시작 전 DB 초기화
+export const clearDatabase = async () => {
+  await prisma.like.deleteMany();
+  await prisma.comment.deleteMany();
+  await prisma.article.deleteMany();
+  await prisma.product.deleteMany();
+  await prisma.alert.deleteMany();
+  await prisma.user.deleteMany();
+};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/test/utils.ts.html b/mission 10/coverage/lcov-report/test/utils.ts.html new file mode 100644 index 000000000..793ae1255 --- /dev/null +++ b/mission 10/coverage/lcov-report/test/utils.ts.html @@ -0,0 +1,181 @@ + + + + + + Code coverage report for test/utils.ts + + + + + + + + + +
+
+

All files / test utils.ts

+
+ +
+ 100% + Statements + 11/11 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 11/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +334x +4x +4x +  +4x +4x +4x +4x +  +  +4x +  +  +  +  +  +4x +  +  +  +  +4x +  +4x +  +  +  +  +  +  +  +  + 
import supertest from "supertest";
+import { app } from "../src/app";
+import { ACCESS_TOKEN_COOKIE_NAME } from "../src/lib/constants";
+ 
+export async function createTestUserAndGetToken() {
+  const email = `test${Date.now()}@test.com`;
+  const password = "password123";
+  const nickname = "테스트닉";
+ 
+  // 회원가입
+  await supertest(app)
+    .post("/users/register")
+    .send({ email, password, nickname })
+    .expect(201);
+ 
+  // 로그인
+  const loginRes = await supertest(app)
+    .post("/users/login")
+    .send({ email, password })
+    .expect(200);
+ 
+  const token = loginRes.body.token;
+ 
+  return {
+    email,
+    password,
+    nickname,
+    token,
+    authHeader: `Bearer ${token}`, // 테스트용 Authorization 헤더
+    cookieHeader: `${ACCESS_TOKEN_COOKIE_NAME}=${token}`, // 필요 시 쿠키용
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/tests/helpers/auth.ts.html b/mission 10/coverage/lcov-report/tests/helpers/auth.ts.html new file mode 100644 index 000000000..a7aee9a9f --- /dev/null +++ b/mission 10/coverage/lcov-report/tests/helpers/auth.ts.html @@ -0,0 +1,205 @@ + + + + + + Code coverage report for tests/helpers/auth.ts + + + + + + + + + +
+
+

All files / tests/helpers auth.ts

+
+ +
+ 94.11% + Statements + 16/17 +
+ + +
+ 71.42% + Branches + 5/7 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 94.11% + Lines + 16/17 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41  +2x +2x +2x +2x +  +  +  +  +  +  +2x +  +  +  +2x +  +2x +  +2x +  +2x +2x +2x +  +  +2x +  +  +  +  +2x +  +2x +2x +  +  +  +2x +  + 
// tests/helpers/auth.ts
+import request from "supertest";
+import { app } from "../../src/app";
+import bcrypt from "bcrypt";
+import { UserRepository } from "../../src/repositories/userRepository";
+ 
+interface TokenResponse {
+  accessToken: string;
+  refreshToken?: string;
+}
+ 
+export async function loginAndGetToken(
+  email?: string,
+  password = "123456"
+): Promise<{ accessToken: string; refreshToken?: string; userId: number }> {
+  const userRepo = new UserRepository();
+ 
+  email = email ?? `test${Date.now()}@test.com`;
+ 
+  let existing = await userRepo.findByEmail(email);
+ 
+  Eif (!existing) {
+    const hashed = await bcrypt.hash(password, 10);
+    existing = await userRepo.createUser(email, "tester", hashed);
+  }
+ 
+  const res = await request(app)
+    .post("/users/login")
+    .send({ email, password })
+    .expect(200);
+ 
+  console.log("Login response body:", res.body);
+ 
+  const { accessToken, refreshToken } = res.body;
+  Iif (!accessToken) {
+    throw new Error("로그인 실패: accessToken이 반환되지 않았습니다.");
+  }
+ 
+  return { accessToken, refreshToken, userId: existing.id };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/tests/helpers/db.ts.html b/mission 10/coverage/lcov-report/tests/helpers/db.ts.html new file mode 100644 index 000000000..effdaaeb6 --- /dev/null +++ b/mission 10/coverage/lcov-report/tests/helpers/db.ts.html @@ -0,0 +1,112 @@ + + + + + + Code coverage report for tests/helpers/db.ts + + + + + + + + + +
+
+

All files / tests/helpers db.ts

+
+ +
+ 100% + Statements + 6/6 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 6/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +101x +  +1x +  +1x +1x +1x +1x +  + 
import { PrismaClient } from "@prisma/client";
+ 
+const prisma = new PrismaClient();
+ 
+export async function clearDatabase() {
+  await prisma.article.deleteMany();
+  await prisma.product.deleteMany();
+  await prisma.user.deleteMany();
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov-report/tests/helpers/index.html b/mission 10/coverage/lcov-report/tests/helpers/index.html new file mode 100644 index 000000000..533db60e0 --- /dev/null +++ b/mission 10/coverage/lcov-report/tests/helpers/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for tests/helpers + + + + + + + + + +
+
+

All files tests/helpers

+
+ +
+ 95.65% + Statements + 22/23 +
+ + +
+ 71.42% + Branches + 5/7 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 95.65% + Lines + 22/23 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
auth.ts +
+
94.11%16/1771.42%5/7100%1/194.11%16/17
db.ts +
+
100%6/6100%0/0100%1/1100%6/6
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/mission 10/coverage/lcov.info b/mission 10/coverage/lcov.info new file mode 100644 index 000000000..e7e2dbac6 --- /dev/null +++ b/mission 10/coverage/lcov.info @@ -0,0 +1,1538 @@ +TN: +SF:src/app.ts +FNF:0 +FNH:0 +DA:1,3 +DA:2,3 +DA:3,3 +DA:4,3 +DA:5,3 +DA:6,3 +DA:7,3 +DA:8,3 +DA:9,3 +DA:11,3 +DA:13,3 +DA:14,3 +DA:15,3 +DA:17,3 +DA:22,3 +DA:24,3 +DA:25,3 +DA:27,3 +DA:29,3 +DA:31,3 +DA:33,3 +DA:34,3 +DA:40,3 +DA:41,3 +LF:24 +LH:24 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/controllers/alertController.ts +FN:5,(anonymous_1) +FN:8,(anonymous_2) +FN:16,(anonymous_3) +FNF:3 +FNH:1 +FNDA:3,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +DA:2,3 +DA:3,3 +DA:5,3 +DA:6,3 +DA:8,3 +DA:9,0 +DA:10,0 +DA:11,0 +DA:12,0 +DA:13,0 +DA:16,3 +DA:17,0 +DA:18,0 +DA:20,0 +DA:21,0 +DA:23,0 +DA:24,0 +DA:27,0 +DA:29,0 +DA:30,0 +DA:34,0 +LF:21 +LH:6 +BRDA:9,0,0,0 +BRDA:9,0,1,0 +BRDA:17,1,0,0 +BRDA:17,1,1,0 +BRDA:23,2,0,0 +BRDA:23,2,1,0 +BRDA:29,3,0,0 +BRDA:29,3,1,0 +BRF:8 +BRH:0 +end_of_record +TN: +SF:src/controllers/articleController.ts +FN:9,(anonymous_1) +FN:21,(anonymous_2) +FN:31,(anonymous_3) +FN:42,(anonymous_4) +FN:57,(anonymous_5) +FNF:5 +FNH:4 +FNDA:0,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:2,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:1,(anonymous_5) +DA:2,3 +DA:3,3 +DA:4,3 +DA:6,3 +DA:8,3 +DA:10,0 +DA:11,0 +DA:13,0 +DA:14,0 +DA:15,0 +DA:17,0 +DA:22,1 +DA:23,1 +DA:24,1 +DA:25,1 +DA:27,0 +DA:32,2 +DA:33,2 +DA:34,2 +DA:35,2 +DA:36,1 +DA:38,0 +DA:43,1 +DA:44,1 +DA:45,1 +DA:46,1 +DA:47,1 +DA:49,1 +DA:51,0 +DA:52,0 +DA:53,0 +DA:58,1 +DA:59,1 +DA:61,1 +DA:62,1 +DA:63,1 +DA:65,0 +DA:66,0 +DA:67,0 +LF:39 +LH:25 +BRDA:11,0,0,0 +BRDA:11,0,1,0 +BRDA:35,1,0,1 +BRDA:35,1,1,1 +BRDA:44,2,0,0 +BRDA:44,2,1,1 +BRDA:51,3,0,0 +BRDA:51,3,1,0 +BRDA:52,4,0,0 +BRDA:52,4,1,0 +BRDA:59,5,0,0 +BRDA:59,5,1,1 +BRDA:65,6,0,0 +BRDA:65,6,1,0 +BRDA:66,7,0,0 +BRDA:66,7,1,0 +BRF:16 +BRH:4 +end_of_record +TN: +SF:src/controllers/commentController.ts +FN:18,(anonymous_1) +FN:30,(anonymous_2) +FN:42,(anonymous_3) +FN:56,(anonymous_4) +FN:69,(anonymous_5) +FN:79,(anonymous_6) +FNF:6 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +DA:2,3 +DA:3,3 +DA:4,3 +DA:6,3 +DA:8,3 +DA:12,3 +DA:17,3 +DA:19,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:26,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:38,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:75,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:85,0 +LF:48 +LH:7 +BRDA:20,0,0,0 +BRDA:20,0,1,0 +BRDA:32,1,0,0 +BRDA:32,1,1,0 +BRDA:44,2,0,0 +BRDA:44,2,1,0 +BRDA:50,3,0,0 +BRDA:50,3,1,0 +BRDA:51,4,0,0 +BRDA:51,4,1,0 +BRDA:58,5,0,0 +BRDA:58,5,1,0 +BRDA:63,6,0,0 +BRDA:63,6,1,0 +BRDA:64,7,0,0 +BRDA:64,7,1,0 +BRF:16 +BRH:0 +end_of_record +TN: +SF:src/controllers/likeController.ts +FN:8,(anonymous_1) +FN:19,(anonymous_2) +FN:30,(anonymous_3) +FN:34,(anonymous_4) +FN:41,(anonymous_5) +FN:45,(anonymous_6) +FNF:6 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +DA:2,3 +DA:3,3 +DA:5,3 +DA:7,3 +DA:9,0 +DA:10,0 +DA:11,0 +DA:12,0 +DA:14,0 +DA:15,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:25,0 +DA:26,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:37,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:48,0 +LF:28 +LH:4 +BRDA:9,0,0,0 +BRDA:9,0,1,0 +BRDA:14,1,0,0 +BRDA:14,1,1,0 +BRDA:20,2,0,0 +BRDA:20,2,1,0 +BRDA:25,3,0,0 +BRDA:25,3,1,0 +BRDA:31,4,0,0 +BRDA:31,4,1,0 +BRDA:42,5,0,0 +BRDA:42,5,1,0 +BRF:12 +BRH:0 +end_of_record +TN: +SF:src/controllers/photoController.ts +FN:6,(anonymous_1) +FNF:1 +FNH:0 +FNDA:0,(anonymous_1) +DA:2,3 +DA:3,3 +DA:5,3 +DA:7,0 +DA:9,0 +DA:10,0 +DA:13,0 +DA:14,0 +DA:16,0 +DA:21,0 +DA:26,0 +LF:11 +LH:3 +BRDA:7,0,0,0 +BRDA:7,0,1,0 +BRDA:9,1,0,0 +BRDA:9,1,1,0 +BRF:4 +BRH:0 +end_of_record +TN: +SF:src/controllers/productController.ts +FN:9,(anonymous_1) +FN:20,(anonymous_2) +FN:30,(anonymous_3) +FN:41,(anonymous_4) +FN:56,(anonymous_5) +FNF:5 +FNH:4 +FNDA:0,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:2,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:1,(anonymous_5) +DA:2,3 +DA:3,3 +DA:4,3 +DA:6,3 +DA:8,3 +DA:10,0 +DA:11,0 +DA:12,0 +DA:13,0 +DA:14,0 +DA:16,0 +DA:21,1 +DA:22,1 +DA:23,1 +DA:24,1 +DA:26,0 +DA:31,2 +DA:32,2 +DA:33,2 +DA:34,2 +DA:35,1 +DA:37,0 +DA:42,1 +DA:43,1 +DA:44,1 +DA:45,1 +DA:46,1 +DA:48,1 +DA:50,0 +DA:51,0 +DA:52,0 +DA:57,1 +DA:58,1 +DA:59,1 +DA:60,1 +DA:61,1 +DA:63,0 +DA:64,0 +DA:65,0 +LF:39 +LH:25 +BRDA:11,0,0,0 +BRDA:11,0,1,0 +BRDA:34,1,0,1 +BRDA:34,1,1,1 +BRDA:43,2,0,0 +BRDA:43,2,1,1 +BRDA:50,3,0,0 +BRDA:50,3,1,0 +BRDA:51,4,0,0 +BRDA:51,4,1,0 +BRDA:58,5,0,0 +BRDA:58,5,1,1 +BRDA:63,6,0,0 +BRDA:63,6,1,0 +BRDA:64,7,0,0 +BRDA:64,7,1,0 +BRF:16 +BRH:4 +end_of_record +TN: +SF:src/controllers/userController.ts +FN:10,(anonymous_1) +FN:23,(anonymous_2) +FN:36,(anonymous_3) +FN:46,(anonymous_4) +FN:60,(anonymous_5) +FN:73,(anonymous_6) +FN:86,(anonymous_7) +FN:93,(anonymous_8) +FNF:8 +FNH:2 +FNDA:2,(anonymous_1) +FNDA:3,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:0,(anonymous_8) +DA:2,3 +DA:3,3 +DA:4,3 +DA:5,3 +DA:7,3 +DA:9,3 +DA:11,2 +DA:12,2 +DA:13,2 +DA:14,1 +DA:16,1 +DA:17,1 +DA:19,0 +DA:24,3 +DA:26,3 +DA:27,3 +DA:28,3 +DA:30,3 +DA:32,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:47,0 +DA:48,0 +DA:50,0 +DA:51,0 +DA:53,0 +DA:55,0 +DA:56,0 +DA:61,0 +DA:62,0 +DA:64,0 +DA:65,0 +DA:67,0 +DA:69,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:80,0 +DA:82,0 +DA:87,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:94,0 +DA:95,0 +LF:50 +LH:17 +BRDA:16,0,0,1 +BRDA:16,0,1,0 +BRDA:24,1,0,0 +BRDA:24,1,1,3 +BRDA:38,2,0,0 +BRDA:38,2,1,0 +BRDA:48,3,0,0 +BRDA:48,3,1,0 +BRDA:55,4,0,0 +BRDA:55,4,1,0 +BRDA:62,5,0,0 +BRDA:62,5,1,0 +BRDA:75,6,0,0 +BRDA:75,6,1,0 +BRDA:77,7,0,0 +BRDA:77,7,1,0 +BRDA:77,8,0,0 +BRDA:77,8,1,0 +BRDA:87,9,0,0 +BRDA:87,9,1,0 +BRF:20 +BRH:2 +end_of_record +TN: +SF:src/dtos/article.dto.ts +FN:30,(anonymous_0) +FN:35,(anonymous_1) +FNF:2 +FNH:2 +FNDA:1,(anonymous_0) +FNDA:1,(anonymous_1) +DA:1,3 +DA:4,3 +DA:14,3 +DA:25,3 +DA:30,1 +DA:35,1 +LF:6 +LH:6 +BRDA:35,0,0,1 +BRDA:35,0,1,1 +BRF:2 +BRH:2 +end_of_record +TN: +SF:src/dtos/product.dto.ts +FN:24,(anonymous_0) +FN:25,(anonymous_1) +FNF:2 +FNH:2 +FNDA:1,(anonymous_0) +FNDA:1,(anonymous_1) +DA:1,3 +DA:5,3 +DA:14,3 +DA:23,3 +DA:24,1 +DA:25,1 +LF:6 +LH:6 +BRDA:25,0,0,1 +BRDA:25,0,1,1 +BRF:2 +BRH:2 +end_of_record +TN: +SF:src/dtos/user.dto.ts +FNF:0 +FNH:0 +DA:1,3 +DA:4,3 +DA:12,3 +DA:19,3 +DA:26,3 +LF:5 +LH:5 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/lib/constants.ts +FNF:0 +FNH:0 +DA:1,3 +DA:3,3 +DA:5,3 +DA:6,3 +DA:8,3 +DA:10,3 +DA:11,3 +DA:12,3 +DA:15,3 +DA:16,3 +DA:17,3 +DA:18,3 +DA:19,3 +DA:20,3 +LF:14 +LH:14 +BRDA:5,0,0,3 +BRDA:5,0,1,0 +BRDA:6,1,0,3 +BRDA:6,1,1,0 +BRDA:8,2,0,3 +BRDA:8,2,1,0 +BRDA:10,3,0,3 +BRDA:10,3,1,0 +BRF:8 +BRH:4 +end_of_record +TN: +SF:src/lib/cookieUtil.ts +FN:4,setTokenCookies +FN:19,clearTokenCookies +FNF:2 +FNH:1 +FNDA:3,setTokenCookies +FNDA:0,clearTokenCookies +DA:2,3 +DA:4,3 +DA:5,3 +DA:11,3 +DA:19,3 +DA:20,0 +DA:21,0 +LF:7 +LH:5 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/lib/prisma.ts +FNF:0 +FNH:0 +DA:1,3 +DA:3,3 +DA:5,3 +LF:3 +LH:3 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/lib/token.ts +FN:7,generateTokens +FN:17,verifyAccessToken +FN:22,verifyRefreshToken +FNF:3 +FNH:1 +FNDA:3,generateTokens +FNDA:0,verifyAccessToken +FNDA:0,verifyRefreshToken +DA:1,3 +DA:2,3 +DA:8,3 +DA:11,3 +DA:14,3 +DA:18,0 +DA:19,0 +DA:23,0 +DA:24,0 +DA:27,3 +LF:10 +LH:6 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/lib/passport/index.ts +FNF:0 +FNH:0 +DA:1,3 +DA:2,3 +DA:3,3 +DA:5,3 +DA:6,3 +DA:7,3 +DA:9,3 +LF:7 +LH:7 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/lib/passport/jwtStrategy.ts +FN:22,(anonymous_1) +FN:29,(anonymous_2) +FN:33,jwtVerify +FNF:3 +FNH:2 +FNDA:4,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:4,jwtVerify +DA:1,3 +DA:2,3 +DA:5,3 +DA:21,3 +DA:23,4 +DA:28,3 +DA:29,0 +DA:34,4 +DA:35,4 +DA:38,4 +DA:40,0 +DA:44,3 +DA:49,3 +LF:13 +LH:11 +BRDA:23,0,0,4 +BRDA:23,0,1,4 +BRF:2 +BRH:2 +end_of_record +TN: +SF:src/lib/passport/localStrategy.ts +FN:10,(anonymous_1) +FNF:1 +FNH:1 +FNDA:4,(anonymous_1) +DA:1,3 +DA:2,3 +DA:3,3 +DA:5,3 +DA:11,4 +DA:12,4 +DA:13,4 +DA:14,0 +DA:17,4 +DA:18,4 +DA:19,1 +DA:22,3 +DA:24,0 +LF:13 +LH:11 +BRDA:13,0,0,0 +BRDA:13,0,1,4 +BRDA:18,1,0,1 +BRDA:18,1,1,3 +BRF:4 +BRH:3 +end_of_record +TN: +SF:src/middlewares/errorHandler.ts +FN:9,errorHandler +FNF:1 +FNH:0 +FNDA:0,errorHandler +DA:1,3 +DA:2,3 +DA:9,3 +DA:10,0 +DA:11,0 +DA:14,0 +DA:15,0 +DA:18,0 +DA:19,0 +LF:9 +LH:3 +BRDA:10,0,0,0 +BRDA:10,0,1,0 +BRDA:14,1,0,0 +BRDA:14,1,1,0 +BRF:4 +BRH:0 +end_of_record +TN: +SF:src/repositories/alertRepository.ts +FN:4,(anonymous_1) +FN:8,(anonymous_2) +FN:15,(anonymous_3) +FN:22,(anonymous_4) +FN:28,(anonymous_5) +FNF:5 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +DA:1,3 +DA:3,3 +DA:5,0 +DA:9,0 +DA:16,0 +DA:23,0 +DA:29,0 +LF:7 +LH:2 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/repositories/articleRepository.ts +FN:5,(anonymous_1) +FN:9,(anonymous_2) +FN:19,(anonymous_3) +FN:26,(anonymous_4) +FN:34,(anonymous_5) +FNF:5 +FNH:5 +FNDA:1,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:4,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:1,(anonymous_5) +DA:1,3 +DA:4,3 +DA:6,1 +DA:10,1 +DA:20,4 +DA:27,1 +DA:28,1 +DA:29,1 +DA:31,1 +DA:35,1 +DA:39,3 +LF:11 +LH:11 +BRDA:28,0,0,1 +BRDA:28,0,1,0 +BRDA:29,1,0,0 +BRDA:29,1,1,1 +BRF:4 +BRH:2 +end_of_record +TN: +SF:src/repositories/commentRepository.ts +FN:4,(anonymous_1) +FN:10,(anonymous_2) +FN:16,(anonymous_3) +FN:20,(anonymous_4) +FN:27,(anonymous_5) +FN:31,(anonymous_6) +FN:41,(anonymous_7) +FNF:7 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +DA:1,3 +DA:3,3 +DA:5,0 +DA:11,0 +DA:17,0 +DA:21,0 +DA:28,0 +DA:32,0 +DA:42,0 +DA:52,3 +LF:10 +LH:3 +BRDA:35,0,0,0 +BRDA:35,0,1,0 +BRDA:36,1,0,0 +BRDA:36,1,1,0 +BRDA:45,2,0,0 +BRDA:45,2,1,0 +BRDA:46,3,0,0 +BRDA:46,3,1,0 +BRF:8 +BRH:0 +end_of_record +TN: +SF:src/repositories/likeRepository.ts +FN:4,(anonymous_1) +FN:8,(anonymous_2) +FN:12,(anonymous_3) +FN:18,(anonymous_4) +FN:24,(anonymous_5) +FN:31,(anonymous_6) +FN:38,(anonymous_7) +FN:44,(anonymous_8) +FN:50,(anonymous_9) +FN:59,(anonymous_10) +FN:68,(anonymous_11) +FN:83,(anonymous_12) +FNF:12 +FNH:1 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:0,(anonymous_9) +FNDA:0,(anonymous_10) +FNDA:1,(anonymous_11) +FNDA:0,(anonymous_12) +DA:1,3 +DA:3,3 +DA:5,0 +DA:9,0 +DA:13,0 +DA:19,0 +DA:25,0 +DA:32,0 +DA:39,0 +DA:45,0 +DA:51,0 +DA:60,0 +DA:69,1 +DA:83,1 +LF:14 +LH:4 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/repositories/productRepository.ts +FN:6,(anonymous_1) +FN:10,(anonymous_2) +FN:27,(anonymous_3) +FN:42,(anonymous_4) +FN:46,(anonymous_5) +FNF:5 +FNH:5 +FNDA:1,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:4,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:1,(anonymous_5) +DA:1,3 +DA:5,3 +DA:7,1 +DA:11,1 +DA:28,4 +DA:43,1 +DA:47,1 +LF:7 +LH:7 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/repositories/userRepository.ts +FN:4,(anonymous_1) +FN:8,(anonymous_2) +FN:15,(anonymous_3) +FN:19,(anonymous_4) +FN:23,(anonymous_5) +FNF:5 +FNH:2 +FNDA:4,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:4,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +DA:1,3 +DA:3,3 +DA:5,4 +DA:9,0 +DA:16,4 +DA:20,0 +DA:24,0 +LF:7 +LH:4 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/routers/alertRouter.ts +FNF:0 +FNH:0 +DA:1,3 +DA:2,3 +DA:3,3 +DA:5,3 +DA:6,3 +DA:8,3 +DA:10,3 +DA:12,3 +LF:8 +LH:8 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/routers/articleRouter.ts +FNF:0 +FNH:0 +DA:1,3 +DA:2,3 +DA:3,3 +DA:5,3 +DA:6,3 +DA:8,3 +DA:9,3 +DA:10,3 +DA:12,3 +DA:13,3 +DA:15,3 +LF:11 +LH:11 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/routers/commentRouter.ts +FNF:0 +FNH:0 +DA:1,3 +DA:2,3 +DA:3,3 +DA:5,3 +DA:6,3 +DA:8,3 +DA:9,3 +DA:10,3 +DA:11,3 +DA:13,3 +DA:14,3 +DA:16,3 +LF:12 +LH:12 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/routers/index.ts +FNF:0 +FNH:0 +DA:1,3 +DA:3,3 +DA:4,3 +DA:5,3 +DA:6,3 +DA:7,3 +DA:8,3 +DA:9,3 +DA:11,3 +DA:13,3 +DA:14,3 +DA:15,3 +DA:16,3 +DA:17,3 +DA:18,3 +DA:19,3 +DA:21,3 +LF:17 +LH:17 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/routers/likeRouter.ts +FNF:0 +FNH:0 +DA:1,3 +DA:2,3 +DA:3,3 +DA:5,3 +DA:6,3 +DA:8,3 +DA:9,3 +DA:10,3 +DA:11,3 +DA:13,3 +LF:10 +LH:10 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/routers/photoRouter.ts +FNF:0 +FNH:0 +DA:1,3 +DA:2,3 +DA:3,3 +DA:4,3 +DA:6,3 +DA:7,3 +DA:8,3 +DA:10,3 +DA:17,3 +LF:9 +LH:9 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/routers/productRouter.ts +FNF:0 +FNH:0 +DA:1,3 +DA:2,3 +DA:3,3 +DA:5,3 +DA:6,3 +DA:9,3 +DA:10,3 +DA:11,3 +DA:14,3 +DA:15,3 +DA:17,3 +LF:11 +LH:11 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/routers/userRouter.ts +FN:11,(anonymous_1) +FN:15,(anonymous_2) +FNF:2 +FNH:2 +FNDA:4,(anonymous_1) +FNDA:4,(anonymous_2) +DA:1,3 +DA:2,3 +DA:3,3 +DA:5,3 +DA:6,3 +DA:8,3 +DA:9,3 +DA:12,4 +DA:20,4 +DA:22,4 +DA:23,1 +DA:28,3 +DA:29,3 +DA:36,3 +DA:41,3 +DA:46,3 +DA:51,3 +DA:56,3 +DA:61,3 +DA:63,3 +LF:20 +LH:20 +BRDA:20,0,0,0 +BRDA:20,0,1,4 +BRDA:22,1,0,1 +BRDA:22,1,1,3 +BRF:4 +BRH:3 +end_of_record +TN: +SF:src/services/alertService.ts +FN:4,(anonymous_0) +FN:7,(anonymous_1) +FN:16,(anonymous_2) +FN:20,(anonymous_3) +FN:34,(anonymous_4) +FNF:5 +FNH:1 +FNDA:9,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +DA:1,3 +DA:2,3 +DA:4,3 +DA:5,9 +DA:8,0 +DA:10,0 +DA:11,0 +DA:13,0 +DA:17,0 +DA:21,0 +DA:23,0 +DA:25,0 +DA:26,0 +DA:29,0 +DA:31,0 +DA:35,0 +LF:16 +LH:4 +BRDA:23,0,0,0 +BRDA:23,0,1,0 +BRDA:25,1,0,0 +BRDA:25,1,1,0 +BRF:4 +BRH:0 +end_of_record +TN: +SF:src/services/articleService.ts +FN:5,(anonymous_0) +FN:8,(anonymous_1) +FN:12,(anonymous_2) +FN:25,(anonymous_3) +FN:29,(anonymous_4) +FN:37,(anonymous_5) +FNF:6 +FNH:5 +FNDA:6,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:2,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:1,(anonymous_5) +DA:1,3 +DA:5,3 +DA:6,6 +DA:9,0 +DA:13,1 +DA:22,1 +DA:26,2 +DA:30,1 +DA:31,1 +DA:32,1 +DA:34,1 +DA:38,1 +DA:39,1 +DA:40,1 +DA:42,1 +DA:46,3 +LF:16 +LH:15 +BRDA:13,0,0,0 +BRDA:13,0,1,1 +BRDA:31,1,0,0 +BRDA:31,1,1,1 +BRDA:32,2,0,0 +BRDA:32,2,1,1 +BRDA:39,3,0,0 +BRDA:39,3,1,1 +BRDA:40,4,0,0 +BRDA:40,4,1,1 +BRF:10 +BRH:5 +end_of_record +TN: +SF:src/services/commentService.ts +FN:6,(anonymous_0) +FN:12,(anonymous_1) +FN:39,(anonymous_2) +FN:66,(anonymous_3) +FN:73,(anonymous_4) +FN:80,(anonymous_5) +FN:84,(anonymous_6) +FNF:7 +FNH:1 +FNDA:3,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +DA:1,3 +DA:2,3 +DA:3,3 +DA:4,3 +DA:6,3 +DA:7,3 +DA:8,3 +DA:9,3 +DA:10,3 +DA:17,0 +DA:18,0 +DA:19,0 +DA:22,0 +DA:28,0 +DA:29,0 +DA:36,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:49,0 +DA:55,0 +DA:56,0 +DA:63,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:81,0 +DA:85,0 +LF:33 +LH:9 +BRDA:18,0,0,0 +BRDA:18,0,1,0 +BRDA:28,1,0,0 +BRDA:28,1,1,0 +BRDA:28,2,0,0 +BRDA:28,2,1,0 +BRDA:45,3,0,0 +BRDA:45,3,1,0 +BRDA:55,4,0,0 +BRDA:55,4,1,0 +BRDA:55,5,0,0 +BRDA:55,5,1,0 +BRDA:68,6,0,0 +BRDA:68,6,1,0 +BRDA:69,7,0,0 +BRDA:69,7,1,0 +BRDA:75,8,0,0 +BRDA:75,8,1,0 +BRDA:76,9,0,0 +BRDA:76,9,1,0 +BRF:20 +BRH:0 +end_of_record +TN: +SF:src/services/likeService.ts +FN:3,(anonymous_0) +FN:6,(anonymous_1) +FN:17,(anonymous_2) +FN:28,(anonymous_3) +FN:32,(anonymous_4) +FNF:5 +FNH:1 +FNDA:3,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +DA:1,3 +DA:3,3 +DA:4,3 +DA:7,0 +DA:8,0 +DA:10,0 +DA:11,0 +DA:12,0 +DA:14,0 +DA:18,0 +DA:19,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:25,0 +DA:29,0 +DA:33,0 +LF:17 +LH:3 +BRDA:8,0,0,0 +BRDA:8,0,1,0 +BRDA:11,1,0,0 +BRDA:11,1,1,0 +BRDA:19,2,0,0 +BRDA:19,2,1,0 +BRDA:22,3,0,0 +BRDA:22,3,1,0 +BRF:8 +BRH:0 +end_of_record +TN: +SF:src/services/productService.ts +FN:7,(anonymous_0) +FN:12,(anonymous_1) +FN:16,(anonymous_2) +FN:28,(anonymous_3) +FN:32,(anonymous_4) +FN:47,(anonymous_5) +FN:61,(anonymous_6) +FNF:7 +FNH:5 +FNDA:3,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:2,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:1,(anonymous_6) +DA:1,3 +DA:2,3 +DA:3,3 +DA:7,3 +DA:8,3 +DA:9,3 +DA:10,3 +DA:13,0 +DA:17,1 +DA:25,1 +DA:29,2 +DA:37,1 +DA:38,1 +DA:39,1 +DA:41,1 +DA:42,1 +DA:44,1 +DA:45,1 +DA:47,1 +DA:49,1 +DA:50,0 +DA:58,1 +DA:62,1 +DA:63,1 +DA:64,1 +DA:66,1 +LF:26 +LH:24 +BRDA:17,0,0,0 +BRDA:17,0,1,1 +BRDA:38,1,0,0 +BRDA:38,1,1,1 +BRDA:39,2,0,0 +BRDA:39,2,1,1 +BRDA:44,3,0,1 +BRDA:44,3,1,0 +BRDA:44,4,0,1 +BRDA:44,4,1,1 +BRDA:63,5,0,0 +BRDA:63,5,1,1 +BRDA:64,6,0,0 +BRDA:64,6,1,1 +BRF:14 +BRH:8 +end_of_record +TN: +SF:src/services/userService.ts +FN:6,(anonymous_1) +FN:9,(anonymous_2) +FN:20,(anonymous_3) +FN:24,(anonymous_4) +FN:34,(anonymous_5) +FN:41,(anonymous_6) +FN:45,(anonymous_7) +FNF:7 +FNH:3 +FNDA:3,(anonymous_1) +FNDA:2,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:3,(anonymous_7) +DA:1,3 +DA:2,3 +DA:3,3 +DA:6,3 +DA:7,3 +DA:10,2 +DA:11,2 +DA:13,1 +DA:14,1 +DA:16,1 +DA:17,1 +DA:21,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:29,0 +DA:31,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:42,0 +DA:46,3 +LF:23 +LH:12 +BRDA:11,0,0,1 +BRDA:11,0,1,1 +BRDA:26,1,0,0 +BRDA:26,1,1,0 +BRDA:27,2,0,0 +BRDA:27,2,1,0 +BRDA:29,3,0,0 +BRDA:29,3,1,0 +BRF:8 +BRH:2 +end_of_record +TN: +SF:src/socket/io.ts +FN:5,initIo +FN:15,getIo +FNF:2 +FNH:2 +FNDA:3,initIo +FNDA:3,getIo +DA:1,3 +DA:3,3 +DA:5,3 +DA:6,3 +DA:12,3 +DA:15,3 +DA:16,3 +DA:17,0 +DA:19,3 +LF:9 +LH:8 +BRDA:16,0,0,0 +BRDA:16,0,1,3 +BRF:2 +BRH:1 +end_of_record +TN: +SF:src/socket/socket.ts +FN:4,registerSocket +FN:7,(anonymous_2) +FNF:2 +FNH:1 +FNDA:3,registerSocket +FNDA:0,(anonymous_2) +DA:1,3 +DA:2,3 +DA:4,3 +DA:5,3 +DA:7,3 +DA:8,0 +DA:10,0 +DA:11,0 +DA:13,0 +DA:14,0 +DA:18,0 +DA:20,0 +LF:12 +LH:5 +BRDA:11,0,0,0 +BRDA:11,0,1,0 +BRF:2 +BRH:0 +end_of_record +TN: +SF:tests/helpers/auth.ts +FN:12,loginAndGetToken +FNF:1 +FNH:1 +FNDA:2,loginAndGetToken +DA:2,2 +DA:3,2 +DA:4,2 +DA:5,2 +DA:12,2 +DA:16,2 +DA:18,2 +DA:20,2 +DA:22,2 +DA:23,2 +DA:24,2 +DA:27,2 +DA:32,2 +DA:34,2 +DA:35,2 +DA:36,0 +DA:39,2 +LF:17 +LH:16 +BRDA:14,0,0,2 +BRDA:18,1,0,2 +BRDA:18,1,1,2 +BRDA:22,2,0,2 +BRDA:22,2,1,0 +BRDA:35,3,0,0 +BRDA:35,3,1,2 +BRF:7 +BRH:5 +end_of_record +TN: +SF:tests/helpers/db.ts +FN:5,clearDatabase +FNF:1 +FNH:1 +FNDA:1,clearDatabase +DA:1,1 +DA:3,1 +DA:5,1 +DA:6,1 +DA:7,1 +DA:8,1 +LF:6 +LH:6 +BRF:0 +BRH:0 +end_of_record diff --git a/mission 10/jest.config.ts b/mission 10/jest.config.ts new file mode 100644 index 000000000..a0eb58c12 --- /dev/null +++ b/mission 10/jest.config.ts @@ -0,0 +1,15 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + roots: ['/tests'], + moduleNameMapper: { + '^@/(.*)$': '/src/$1', + }, + setupFilesAfterEnv: [], + clearMocks: true, + restoreMocks: true, + collectCoverage: true, + coverageDirectory: '/coverage', + coverageReporters: ['text', 'lcov'], +}; diff --git a/mission 10/package-lock.json b/mission 10/package-lock.json new file mode 100644 index 000000000..df2c9927d --- /dev/null +++ b/mission 10/package-lock.json @@ -0,0 +1,12632 @@ +{ + "name": "mission3", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mission3", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@prisma/client": "^6.13.0", + "aws-sdk": "^2.1692.0", + "bcrypt": "^6.0.0", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^17.2.2", + "express": "^5.1.0", + "http-status": "^2.1.0", + "multer": "^2.0.2", + "multer-s3": "^3.0.1", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", + "passport-local": "^1.0.0", + "socket.io": "^4.8.1", + "tsx": "^4.20.5", + "ws": "^8.18.3", + "zod": "^4.0.14" + }, + "devDependencies": { + "@types/aws-sdk": "^0.0.42", + "@types/bcrypt": "^6.0.0", + "@types/cookie-parser": "^1.4.9", + "@types/cors": "^2.8.19", + "@types/express": "^5.0.3", + "@types/jest": "^30.0.0", + "@types/jsonwebtoken": "^9.0.10", + "@types/multer": "^2.0.0", + "@types/multer-s3": "^3.0.3", + "@types/node": "^24.3.1", + "@types/passport": "^1.0.17", + "@types/passport-jwt": "^4.0.1", + "@types/passport-local": "^1.0.38", + "@types/uuid": "^10.0.0", + "jest": "^29.7.0", + "prisma": "^6.15.0", + "ts-jest": "^29.4.5", + "ts-node": "^10.9.2", + "ts-node-dev": "^2.0.0", + "typescript": "^5.9.3" + } + }, + "node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/crc32c": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", + "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", + "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-s3": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.933.0.tgz", + "integrity": "sha512-KxwZvdxdCeWK6o8mpnb+kk7Kgb8V+8AjTwSXUWH1UAD85B0tjdo1cSfE5zoR5fWGol4Ml5RLez12a6LPhsoTqA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.932.0", + "@aws-sdk/credential-provider-node": "3.933.0", + "@aws-sdk/middleware-bucket-endpoint": "3.930.0", + "@aws-sdk/middleware-expect-continue": "3.930.0", + "@aws-sdk/middleware-flexible-checksums": "3.932.0", + "@aws-sdk/middleware-host-header": "3.930.0", + "@aws-sdk/middleware-location-constraint": "3.930.0", + "@aws-sdk/middleware-logger": "3.930.0", + "@aws-sdk/middleware-recursion-detection": "3.933.0", + "@aws-sdk/middleware-sdk-s3": "3.932.0", + "@aws-sdk/middleware-ssec": "3.930.0", + "@aws-sdk/middleware-user-agent": "3.932.0", + "@aws-sdk/region-config-resolver": "3.930.0", + "@aws-sdk/signature-v4-multi-region": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@aws-sdk/util-endpoints": "3.930.0", + "@aws-sdk/util-user-agent-browser": "3.930.0", + "@aws-sdk/util-user-agent-node": "3.932.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.2", + "@smithy/eventstream-serde-browser": "^4.2.5", + "@smithy/eventstream-serde-config-resolver": "^4.3.5", + "@smithy/eventstream-serde-node": "^4.2.5", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-blob-browser": "^4.2.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/hash-stream-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/md5-js": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.9", + "@smithy/middleware-retry": "^4.4.9", + "@smithy/middleware-serde": "^4.2.5", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.5", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.8", + "@smithy/util-defaults-mode-node": "^4.2.11", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-stream": "^4.5.6", + "@smithy/util-utf8": "^4.2.0", + "@smithy/util-waiter": "^4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.933.0.tgz", + "integrity": "sha512-zwGLSiK48z3PzKpQiDMKP85+fpIrPMF1qQOQW9OW7BGj5AuBZIisT2O4VzIgYJeh+t47MLU7VgBQL7muc+MJDg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.932.0", + "@aws-sdk/middleware-host-header": "3.930.0", + "@aws-sdk/middleware-logger": "3.930.0", + "@aws-sdk/middleware-recursion-detection": "3.933.0", + "@aws-sdk/middleware-user-agent": "3.932.0", + "@aws-sdk/region-config-resolver": "3.930.0", + "@aws-sdk/types": "3.930.0", + "@aws-sdk/util-endpoints": "3.930.0", + "@aws-sdk/util-user-agent-browser": "3.930.0", + "@aws-sdk/util-user-agent-node": "3.932.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.2", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.9", + "@smithy/middleware-retry": "^4.4.9", + "@smithy/middleware-serde": "^4.2.5", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.5", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.8", + "@smithy/util-defaults-mode-node": "^4.2.11", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.932.0.tgz", + "integrity": "sha512-AS8gypYQCbNojwgjvZGkJocC2CoEICDx9ZJ15ILsv+MlcCVLtUJSRSx3VzJOUY2EEIaGLRrPNlIqyn/9/fySvA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.930.0", + "@aws-sdk/xml-builder": "3.930.0", + "@smithy/core": "^3.18.2", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/signature-v4": "^5.3.5", + "@smithy/smithy-client": "^4.9.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.932.0.tgz", + "integrity": "sha512-ozge/c7NdHUDyHqro6+P5oHt8wfKSUBN+olttiVfBe9Mw3wBMpPa3gQ0pZnG+gwBkKskBuip2bMR16tqYvUSEA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.932.0.tgz", + "integrity": "sha512-b6N9Nnlg8JInQwzBkUq5spNaXssM3h3zLxGzpPrnw0nHSIWPJPTbZzA5Ca285fcDUFuKP+qf3qkuqlAjGOdWhg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.5", + "@smithy/types": "^4.9.0", + "@smithy/util-stream": "^4.5.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.933.0.tgz", + "integrity": "sha512-HygGyKuMG5AaGXsmM0d81miWDon55xwalRHB3UmDg3QBhtunbNIoIaWUbNTKuBZXcIN6emeeEZw/YgSMqLc0YA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.932.0", + "@aws-sdk/credential-provider-env": "3.932.0", + "@aws-sdk/credential-provider-http": "3.932.0", + "@aws-sdk/credential-provider-process": "3.932.0", + "@aws-sdk/credential-provider-sso": "3.933.0", + "@aws-sdk/credential-provider-web-identity": "3.933.0", + "@aws-sdk/nested-clients": "3.933.0", + "@aws-sdk/types": "3.930.0", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.933.0.tgz", + "integrity": "sha512-L2dE0Y7iMLammQewPKNeEh1z/fdJyYEU+/QsLBD9VEh+SXcN/FIyTi21Isw8wPZN6lMB9PDVtISzBnF8HuSFrw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.932.0", + "@aws-sdk/credential-provider-http": "3.932.0", + "@aws-sdk/credential-provider-ini": "3.933.0", + "@aws-sdk/credential-provider-process": "3.932.0", + "@aws-sdk/credential-provider-sso": "3.933.0", + "@aws-sdk/credential-provider-web-identity": "3.933.0", + "@aws-sdk/types": "3.930.0", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.932.0.tgz", + "integrity": "sha512-BodZYKvT4p/Dkm28Ql/FhDdS1+p51bcZeMMu2TRtU8PoMDHnVDhHz27zASEKSZwmhvquxHrZHB0IGuVqjZUtSQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.933.0.tgz", + "integrity": "sha512-/R1DBR7xNcuZIhS2RirU+P2o8E8/fOk+iLAhbqeSTq+g09fP/F6W7ouFpS5eVE2NIfWG7YBFoVddOhvuqpn51g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-sso": "3.933.0", + "@aws-sdk/core": "3.932.0", + "@aws-sdk/token-providers": "3.933.0", + "@aws-sdk/types": "3.930.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.933.0.tgz", + "integrity": "sha512-c7Eccw2lhFx2/+qJn3g+uIDWRuWi2A6Sz3PVvckFUEzPsP0dPUo19hlvtarwP5GzrsXn0yEPRVhpewsIaSCGaQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.932.0", + "@aws-sdk/nested-clients": "3.933.0", + "@aws-sdk/types": "3.930.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/lib-storage": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.933.0.tgz", + "integrity": "sha512-Le939WQra9y8P2/l5Ujqsn8+HrWK0dhiAsM0L80SDyW7S0wJZJKi6fBOJ9jxln7tnDfPjoWAWp0moeDf/HD0uQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.9", + "@smithy/smithy-client": "^4.9.5", + "buffer": "5.6.0", + "events": "3.3.0", + "stream-browserify": "3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-s3": "^3.933.0" + } + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.930.0.tgz", + "integrity": "sha512-cnCLWeKPYgvV4yRYPFH6pWMdUByvu2cy2BAlfsPpvnm4RaVioztyvxmQj5PmVN5fvWs5w/2d6U7le8X9iye2sA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.930.0", + "@aws-sdk/util-arn-parser": "3.893.0", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-config-provider": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-expect-continue": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.930.0.tgz", + "integrity": "sha512-5HEQ+JU4DrLNWeY27wKg/jeVa8Suy62ivJHOSUf6e6hZdVIMx0h/kXS1fHEQNNiLu2IzSEP/bFXsKBaW7x7s0g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.930.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.932.0.tgz", + "integrity": "sha512-hyvRz/XS/0HTHp9/Ld1mKwpOi7bZu5olI42+T112rkCTbt1bewkygzEl4oflY4H7cKMamQusYoL0yBUD/QSEvA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-crypto/util": "5.2.0", + "@aws-sdk/core": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@smithy/is-array-buffer": "^4.2.0", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-stream": "^4.5.6", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.930.0.tgz", + "integrity": "sha512-x30jmm3TLu7b/b+67nMyoV0NlbnCVT5DI57yDrhXAPCtdgM1KtdLWt45UcHpKOm1JsaIkmYRh2WYu7Anx4MG0g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.930.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-location-constraint": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.930.0.tgz", + "integrity": "sha512-QIGNsNUdRICog+LYqmtJ03PLze6h2KCORXUs5td/hAEjVP5DMmubhtrGg1KhWyctACluUH/E/yrD14p4pRXxwA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.930.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.930.0.tgz", + "integrity": "sha512-vh4JBWzMCBW8wREvAwoSqB2geKsZwSHTa0nSt0OMOLp2PdTYIZDi0ZiVMmpfnjcx9XbS6aSluLv9sKx4RrG46A==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.930.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.933.0.tgz", + "integrity": "sha512-qgrMlkVKzTCAdNw2A05DC2sPBo0KRQ7wk+lbYSRJnWVzcrceJhnmhoZVV5PFv7JtchK7sHVcfm9lcpiyd+XaCA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.930.0", + "@aws/lambda-invoke-store": "^0.2.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.932.0.tgz", + "integrity": "sha512-bYMHxqQzseaAP9Z5qLI918z5AtbAnZRRtFi3POb4FLZyreBMgCgBNaPkIhdgywnkqaydTWvbMBX4s9f4gUwlTw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@aws-sdk/util-arn-parser": "3.893.0", + "@smithy/core": "^3.18.2", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/signature-v4": "^5.3.5", + "@smithy/smithy-client": "^4.9.5", + "@smithy/types": "^4.9.0", + "@smithy/util-config-provider": "^4.2.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-stream": "^4.5.6", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-ssec": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.930.0.tgz", + "integrity": "sha512-N2/SvodmaDS6h7CWfuapt3oJyn1T2CBz0CsDIiTDv9cSagXAVFjPdm2g4PFJqrNBeqdDIoYBnnta336HmamWHg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.930.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.932.0.tgz", + "integrity": "sha512-9BGTbJyA/4PTdwQWE9hAFIJGpsYkyEW20WON3i15aDqo5oRZwZmqaVageOD57YYqG8JDJjvcwKyDdR4cc38dvg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@aws-sdk/util-endpoints": "3.930.0", + "@smithy/core": "^3.18.2", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.933.0.tgz", + "integrity": "sha512-o1GX0+IPlFi/D8ei9y/jj3yucJWNfPnbB5appVBWevAyUdZA5KzQ2nK/hDxiu9olTZlFEFpf1m1Rn3FaGxHqsw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.932.0", + "@aws-sdk/middleware-host-header": "3.930.0", + "@aws-sdk/middleware-logger": "3.930.0", + "@aws-sdk/middleware-recursion-detection": "3.933.0", + "@aws-sdk/middleware-user-agent": "3.932.0", + "@aws-sdk/region-config-resolver": "3.930.0", + "@aws-sdk/types": "3.930.0", + "@aws-sdk/util-endpoints": "3.930.0", + "@aws-sdk/util-user-agent-browser": "3.930.0", + "@aws-sdk/util-user-agent-node": "3.932.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.2", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.9", + "@smithy/middleware-retry": "^4.4.9", + "@smithy/middleware-serde": "^4.2.5", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.5", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.8", + "@smithy/util-defaults-mode-node": "^4.2.11", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.930.0.tgz", + "integrity": "sha512-KL2JZqH6aYeQssu1g1KuWsReupdfOoxD6f1as2VC+rdwYFUu4LfzMsFfXnBvvQWWqQ7rZHWOw1T+o5gJmg7Dzw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.930.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.932.0.tgz", + "integrity": "sha512-NCIRJvoRc9246RZHIusY1+n/neeG2yGhBGdKhghmrNdM+mLLN6Ii7CKFZjx3DhxtpHMpl1HWLTMhdVrGwP2upw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-sdk-s3": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/signature-v4": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.933.0.tgz", + "integrity": "sha512-Qzq7zj9yXUgAAJEbbmqRhm0jmUndl8nHG0AbxFEfCfQRVZWL96Qzx0mf8lYwT9hIMrXncLwy31HOthmbXwFRwQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.932.0", + "@aws-sdk/nested-clients": "3.933.0", + "@aws-sdk/types": "3.930.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.930.0.tgz", + "integrity": "sha512-we/vaAgwlEFW7IeftmCLlLMw+6hFs3DzZPJw7lVHbj/5HJ0bz9gndxEsS2lQoeJ1zhiiLqAqvXxmM43s0MBg0A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-arn-parser": { + "version": "3.893.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.893.0.tgz", + "integrity": "sha512-u8H4f2Zsi19DGnwj5FSZzDMhytYF/bCh37vAtBsn3cNDL3YG578X5oc+wSX54pM3tOxS+NY7tvOAo52SW7koUA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.930.0.tgz", + "integrity": "sha512-M2oEKBzzNAYr136RRc6uqw3aWlwCxqTP1Lawps9E1d2abRPvl1p1ztQmmXp1Ak4rv8eByIZ+yQyKQ3zPdRG5dw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.930.0", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-endpoints": "^3.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.893.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.893.0.tgz", + "integrity": "sha512-T89pFfgat6c8nMmpI8eKjBcDcgJq36+m9oiXbcUzeU55MP9ZuGgBomGjGnHaEyF36jenW9gmg3NfZDm0AO2XPg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.930.0.tgz", + "integrity": "sha512-q6lCRm6UAe+e1LguM5E4EqM9brQlDem4XDcQ87NzEvlTW6GzmNCO0w1jS0XgCFXQHjDxjdlNFX+5sRbHijwklg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.930.0", + "@smithy/types": "^4.9.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.932.0.tgz", + "integrity": "sha512-/kC6cscHrZL74TrZtgiIL5jJNbVsw9duGGPurmaVgoCbP7NnxyaSWEurbNV3VPNPhNE3bV3g4Ci+odq+AlsYQg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.930.0.tgz", + "integrity": "sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "fast-xml-parser": "5.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws/lambda-invoke-store": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.0.tgz", + "integrity": "sha512-D1jAmAZQYMoPiacfgNf7AWhg3DFN3Wq/vQv3WINt9znwjzHp2x+WzdJFxxj7xZL7V1U79As6G8f7PorMYWBKsQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/remapping": "^2.3.5", + "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, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "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, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.5" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "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.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "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, + "license": "MIT" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "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/console/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/console/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, + "license": "MIT", + "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/@jest/console/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, + "license": "MIT" + }, + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console/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, + "license": "MIT", + "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/console/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, + "license": "MIT", + "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/console/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, + "license": "MIT", + "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/@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, + "license": "MIT", + "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/core/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core/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, + "license": "MIT", + "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/core/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, + "license": "MIT", + "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/@jest/core/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/core/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, + "license": "MIT" + }, + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/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, + "license": "MIT", + "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/core/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, + "license": "MIT", + "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/core/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, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core/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, + "license": "MIT", + "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/core/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, + "license": "MIT", + "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/core/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, + "license": "MIT", + "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/@jest/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@jest/core/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@jest/diff-sequences": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", + "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "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, + "license": "MIT", + "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/environment/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/environment/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, + "license": "MIT", + "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/@jest/environment/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, + "license": "MIT" + }, + "node_modules/@jest/environment/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/environment/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, + "license": "MIT", + "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/environment/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, + "license": "MIT", + "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/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "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": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", + "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect/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, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect/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, + "license": "MIT", + "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/@jest/expect/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, + "license": "MIT" + }, + "node_modules/@jest/expect/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/expect/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/expect/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, + "license": "MIT", + "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/@jest/expect/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, + "license": "MIT", + "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/expect/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, + "license": "MIT", + "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/expect/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, + "license": "MIT", + "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/expect/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, + "license": "MIT", + "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/expect/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, + "license": "MIT", + "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/@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, + "license": "MIT", + "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/fake-timers/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers/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, + "license": "MIT", + "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/@jest/fake-timers/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, + "license": "MIT" + }, + "node_modules/@jest/fake-timers/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/fake-timers/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/fake-timers/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, + "license": "MIT", + "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/fake-timers/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, + "license": "MIT", + "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/fake-timers/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, + "license": "MIT", + "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/fake-timers/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, + "license": "MIT", + "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/@jest/get-type": { + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", + "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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, + "license": "MIT", + "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/globals/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals/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, + "license": "MIT", + "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/@jest/globals/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, + "license": "MIT" + }, + "node_modules/@jest/globals/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/globals/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, + "license": "MIT", + "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/globals/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, + "license": "MIT", + "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/pattern": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", + "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-regex-util": "30.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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, + "license": "MIT", + "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/@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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters/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, + "license": "MIT", + "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/reporters/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, + "license": "MIT", + "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/@jest/reporters/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/reporters/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, + "license": "MIT" + }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/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, + "license": "BSD-3-Clause", + "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/@jest/reporters/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/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, + "license": "MIT", + "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/reporters/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, + "license": "MIT", + "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/reporters/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, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters/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, + "license": "MIT", + "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/reporters/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, + "license": "MIT", + "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/reporters/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, + "license": "MIT", + "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/@jest/reporters/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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, + "license": "MIT", + "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/source-map/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "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, + "license": "MIT", + "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-result/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result/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, + "license": "MIT", + "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/@jest/test-result/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, + "license": "MIT" + }, + "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, + "license": "MIT", + "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/test-sequencer/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer/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, + "license": "MIT", + "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/@jest/test-sequencer/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, + "license": "MIT" + }, + "node_modules/@jest/test-sequencer/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/test-sequencer/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, + "license": "MIT", + "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/test-sequencer/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, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer/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, + "license": "MIT", + "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/test-sequencer/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, + "license": "MIT", + "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/test-sequencer/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@jest/transform": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz", + "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/types": "30.2.0", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.1", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-util": "30.2.0", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/types": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", + "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@prisma/client": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.13.0.tgz", + "integrity": "sha512-8m2+I3dQovkV8CkDMluiwEV1TxV9EXdT6xaCz39O6jYw7mkf5gwfmi+cL4LJsEPwz5tG7sreBwkRpEMJedGYUQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "prisma": "*", + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@prisma/config": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.15.0.tgz", + "integrity": "sha512-KMEoec9b2u6zX0EbSEx/dRpx1oNLjqJEBZYyK0S3TTIbZ7GEGoVyGyFRk4C72+A38cuPLbfQGQvgOD+gBErKlA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "c12": "3.1.0", + "deepmerge-ts": "7.1.5", + "effect": "3.16.12", + "empathic": "2.0.0" + } + }, + "node_modules/@prisma/debug": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.15.0.tgz", + "integrity": "sha512-y7cSeLuQmyt+A3hstAs6tsuAiVXSnw9T55ra77z0nbNkA8Lcq9rNcQg6PI00by/+WnE/aMRJ/W7sZWn2cgIy1g==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.15.0.tgz", + "integrity": "sha512-opITiR5ddFJ1N2iqa7mkRlohCZqVSsHhRcc29QXeldMljOf4FSellLT0J5goVb64EzRTKcIDeIsJBgmilNcKxA==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/fetch-engine": "6.15.0", + "@prisma/get-platform": "6.15.0" + } + }, + "node_modules/@prisma/engines-version": { + "version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb.tgz", + "integrity": "sha512-a/46aK5j6L3ePwilZYEgYDPrhBQ/n4gYjLxT5YncUTJJNRnTCVjPF86QdzUOLRdYjCLfhtZp9aum90W0J+trrg==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.15.0.tgz", + "integrity": "sha512-xcT5f6b+OWBq6vTUnRCc7qL+Im570CtwvgSj+0MTSGA1o9UDSKZ/WANvwtiRXdbYWECpyC3CukoG3A04VTAPHw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/get-platform": "6.15.0" + } + }, + "node_modules/@prisma/get-platform": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.15.0.tgz", + "integrity": "sha512-Jbb+Xbxyp05NSR1x2epabetHiXvpO8tdN2YNoWoA/ZsbYyxxu/CO/ROBauIFuMXs3Ti+W7N7SJtWsHGaWte9Rg==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", + "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "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, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.5.tgz", + "integrity": "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.2.0.tgz", + "integrity": "sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.2.1.tgz", + "integrity": "sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-base64": "^4.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.3.tgz", + "integrity": "sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-config-provider": "^4.2.0", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/core": { + "version": "3.18.4", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.18.4.tgz", + "integrity": "sha512-o5tMqPZILBvvROfC8vC+dSVnWJl9a0u9ax1i1+Bq8515eYjUJqqk5XjjEsDLoeL5dSqGSh6WGdVx1eJ1E/Nwhw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/middleware-serde": "^4.2.6", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-stream": "^4.5.6", + "@smithy/util-utf8": "^4.2.0", + "@smithy/uuid": "^1.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.5.tgz", + "integrity": "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.5.tgz", + "integrity": "sha512-Ogt4Zi9hEbIP17oQMd68qYOHUzmH47UkK7q7Gl55iIm9oKt27MUGrC5JfpMroeHjdkOliOA4Qt3NQ1xMq/nrlA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.9.0", + "@smithy/util-hex-encoding": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-browser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.5.tgz", + "integrity": "sha512-HohfmCQZjppVnKX2PnXlf47CW3j92Ki6T/vkAT2DhBR47e89pen3s4fIa7otGTtrVxmj7q+IhH0RnC5kpR8wtw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.5.tgz", + "integrity": "sha512-ibjQjM7wEXtECiT6my1xfiMH9IcEczMOS6xiCQXoUIYSj5b1CpBbJ3VYbdwDy8Vcg5JHN7eFpOCGk8nyZAltNQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-node": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.5.tgz", + "integrity": "sha512-+elOuaYx6F2H6x1/5BQP5ugv12nfJl66GhxON8+dWVUEDJ9jah/A0tayVdkLRP0AeSac0inYkDz5qBFKfVp2Gg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.5.tgz", + "integrity": "sha512-G9WSqbST45bmIFaeNuP/EnC19Rhp54CcVdX9PDL1zyEB514WsDVXhlyihKlGXnRycmHNmVv88Bvvt4EYxWef/Q==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-codec": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.6.tgz", + "integrity": "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.5", + "@smithy/querystring-builder": "^4.2.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-blob-browser": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.2.6.tgz", + "integrity": "sha512-8P//tA8DVPk+3XURk2rwcKgYwFvwGwmJH/wJqQiSKwXZtf/LiZK+hbUZmPj/9KzM+OVSwe4o85KTp5x9DUZTjw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/chunked-blob-reader": "^5.2.0", + "@smithy/chunked-blob-reader-native": "^4.2.1", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-node": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.5.tgz", + "integrity": "sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-stream-node": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.2.5.tgz", + "integrity": "sha512-6+do24VnEyvWcGdHXomlpd0m8bfZePpUKBy7m311n+JuRwug8J4dCanJdTymx//8mi0nlkflZBvJe+dEO/O12Q==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.5.tgz", + "integrity": "sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.0.tgz", + "integrity": "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/md5-js": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.2.5.tgz", + "integrity": "sha512-Bt6jpSTMWfjCtC0s79gZ/WZ1w90grfmopVOWqkI2ovhjpD5Q2XRXuecIPB9689L2+cCySMbaXDhBPU56FKNDNg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.5.tgz", + "integrity": "sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "4.3.11", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.3.11.tgz", + "integrity": "sha512-eJXq9VJzEer1W7EQh3HY2PDJdEcEUnv6sKuNt4eVjyeNWcQFS4KmnY+CKkYOIR6tSqarn6bjjCqg1UB+8UJiPQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.18.4", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-middleware": "^4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "4.4.11", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.11.tgz", + "integrity": "sha512-EL5OQHvFOKneJVRgzRW4lU7yidSwp/vRJOe542bHgExN3KNThr1rlg0iE4k4SnA+ohC+qlUxoK+smKeAYPzfAQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/service-error-classification": "^4.2.5", + "@smithy/smithy-client": "^4.9.7", + "@smithy/types": "^4.9.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/uuid": "^1.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.6.tgz", + "integrity": "sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.5.tgz", + "integrity": "sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.5.tgz", + "integrity": "sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.5.tgz", + "integrity": "sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/querystring-builder": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.5.tgz", + "integrity": "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.5.tgz", + "integrity": "sha512-RlaL+sA0LNMp03bf7XPbFmT5gN+w3besXSWMkA8rcmxLSVfiEXElQi4O2IWwPfxzcHkxqrwBFMbngB8yx/RvaQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.5.tgz", + "integrity": "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "@smithy/util-uri-escape": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.5.tgz", + "integrity": "sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.5.tgz", + "integrity": "sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.0.tgz", + "integrity": "sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.5.tgz", + "integrity": "sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.2.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-hex-encoding": "^4.2.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-uri-escape": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "4.9.7", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.9.7.tgz", + "integrity": "sha512-pskaE4kg0P9xNQWihfqlTMyxyFR3CH6Sr6keHYghgyqqDXzjl2QJg5lAzuVe/LzZiOzcbcVtxKYi1/fZPt/3DA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.18.4", + "@smithy/middleware-endpoint": "^4.3.11", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-stream": "^4.5.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.9.0.tgz", + "integrity": "sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.5.tgz", + "integrity": "sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/querystring-parser": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-base64": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.0.tgz", + "integrity": "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.0.tgz", + "integrity": "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.1.tgz", + "integrity": "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.0.tgz", + "integrity": "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.0.tgz", + "integrity": "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.10.tgz", + "integrity": "sha512-3iA3JVO1VLrP21FsZZpMCeF93aqP3uIOMvymAT3qHIJz2YlgDeRvNUspFwCNqd/j3qqILQJGtsVQnJZICh/9YA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^4.2.5", + "@smithy/smithy-client": "^4.9.7", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "4.2.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.13.tgz", + "integrity": "sha512-PTc6IpnpSGASuzZAgyUtaVfOFpU0jBD2mcGwrgDuHf7PlFgt5TIPxCYBDbFQs06jxgeV3kd/d/sok1pzV0nJRg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/config-resolver": "^4.4.3", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/smithy-client": "^4.9.7", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-endpoints": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.5.tgz", + "integrity": "sha512-3O63AAWu2cSNQZp+ayl9I3NapW1p1rR5mlVHcF6hAB1dPZUQFfRPYtplWX/3xrzWthPGj5FqB12taJJCfH6s8A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.0.tgz", + "integrity": "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.5.tgz", + "integrity": "sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.5.tgz", + "integrity": "sha512-GBj3+EZBbN4NAqJ/7pAhsXdfzdlznOh8PydUijy6FpNIMnHPSMO2/rP4HKu+UFeikJxShERk528oy7GT79YiJg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/service-error-classification": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.6.tgz", + "integrity": "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-hex-encoding": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.0.tgz", + "integrity": "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", + "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-waiter": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.5.tgz", + "integrity": "sha512-Dbun99A3InifQdIrsXZ+QLcC0PGBPAdrl4cj1mTgJvyc9N2zf7QSxg8TBkzsCmGJdE3TLbO9ycwpY0EkWahQ/g==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/uuid": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.0.tgz", + "integrity": "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/aws-sdk": { + "version": "0.0.42", + "resolved": "https://registry.npmjs.org/@types/aws-sdk/-/aws-sdk-0.0.42.tgz", + "integrity": "sha512-zIgLukZrf0/s+oAKxLMHgZFDDjDpuJ95hbE9DiNGrmNGNM7odIt99rHLWVwnOYdF0TNjF0reQeL/mcadAIqljg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "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.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-/oJGukuH3D2+D+3H4JWLaAsJ/ji86dhRidzZ/Od7H/i8g+aCmvkeCc6Ni/f9uxGLSQVCRZkX2/lqEFG2BvWtlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie-parser": { + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.9.tgz", + "integrity": "sha512-tGZiZ2Gtc4m3wIdLkZ8mkj1T6CEHb35+VApbL2T14Dew8HA7c+04dmKqsKRNC+8RJPm16JEK0tFSwdZqubfc4g==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz", + "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", + "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", + "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^30.0.0", + "pretty-format": "^30.0.0" + } + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/multer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz", + "integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/multer-s3": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/multer-s3/-/multer-s3-3.0.3.tgz", + "integrity": "sha512-VgWygI9UwyS7loLithUUi0qAMIDWdNrERS2Sb06UuPYiLzKuIFn2NgL7satyl4v8sh/LLoU7DiPanvbQaRg9Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@aws-sdk/client-s3": "^3.0.0", + "@types/multer": "*", + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "24.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz", + "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~7.10.0" + } + }, + "node_modules/@types/passport": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", + "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/passport-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-Y0Ykz6nWP4jpxgEUYq8NoVZeCQPo1ZndJLfapI249g1jHChvRfZRO/LS3tqu26YgAS/laI1qx98sYGz0IalRXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/jsonwebtoken": "*", + "@types/passport-strategy": "*" + } + }, + "node_modules/@types/passport-local": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.38.tgz", + "integrity": "sha512-nsrW4A963lYE7lNTv9cr5WmiUD1ibYJvWrpE13oxApFsRt77b0RdtZvKbCdNIY4v/QZ6TRQWaDDEwV1kCTmcXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-strategy": "*" + } + }, + "node_modules/@types/passport-strategy": { + "version": "0.2.38", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", + "integrity": "sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", + "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.8", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", + "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/strip-json-comments": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", + "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.34", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.34.tgz", + "integrity": "sha512-KExbHVa92aJpw9WDQvzBaGVE2/Pz+pLZQloT2hjL8IqsZnV62rlPOYvNnLmf/L2dyllfVUOVBj64M0z/46eR2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "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, + "license": "ISC", + "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==", + "license": "MIT" + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sdk": { + "version": "2.1692.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1692.0.tgz", + "integrity": "sha512-x511uiJ/57FIsbgUe5csJ13k3uzu25uWQE+XqfBis/sB0SFoiElJWXRkgEAUh0U6n40eT3ay5Ue4oPkRMu1LYw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.16.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "util": "^0.12.4", + "uuid": "8.0.0", + "xml2js": "0.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aws-sdk/node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "license": "MIT", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/aws-sdk/node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", + "license": "MIT", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/aws-sdk/node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "license": "BSD-3-Clause" + }, + "node_modules/babel-plugin-istanbul": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz", + "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "workspaces": [ + "test/babel-8" + ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.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, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.23", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.23.tgz", + "integrity": "sha512-616V5YX4bepJFzNyOfce5Fa8fDJMfoxzOIzDCZwaGL8MKVpFrXqfNUoIpRn9YMI5pXf/VKgzjB4htFMsFKKdiQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.0", + "node-gyp-build": "^4.8.4" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/bowser": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.12.1.tgz", + "integrity": "sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.27.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz", + "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", + "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" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.8.19", + "caniuse-lite": "^1.0.30001751", + "electron-to-chromium": "^1.5.238", + "node-releases": "^2.0.26", + "update-browserslist-db": "^1.1.4" + }, + "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, + "license": "MIT", + "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, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "license": "MIT", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "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==", + "license": "BSD-3-Clause" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/c12": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", + "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.3", + "confbox": "^0.2.2", + "defu": "^6.1.4", + "dotenv": "^16.6.1", + "exsolve": "^1.0.7", + "giget": "^2.0.0", + "jiti": "^2.4.2", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^1.0.0", + "pkg-types": "^2.2.0", + "rc9": "^2.1.2" + }, + "peerDependencies": { + "magicast": "^0.3.5" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } + } + }, + "node_modules/c12/node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "devOptional": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001753", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001753.tgz", + "integrity": "sha512-Bj5H35MD/ebaOV4iDLqPEtiliTN29qkGtEHCwawWn4cYm+bPJM2NsaP30vtZcnERClMzp52J4+aw2UNbK4o+zw==", + "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" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ci-info": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "consola": "^3.2.3" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "license": "MIT", + "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==", + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "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, + "license": "MIT", + "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-jest/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/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, + "license": "MIT", + "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/create-jest/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, + "license": "MIT" + }, + "node_modules/create-jest/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/create-jest/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, + "license": "MIT", + "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/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, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", + "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": 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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deepmerge-ts": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", + "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dotenv": { + "version": "17.2.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", + "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/dynamic-dedupe": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", + "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + } + }, + "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==", + "license": "Apache-2.0", + "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", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/effect": { + "version": "3.16.12", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.16.12.tgz", + "integrity": "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "fast-check": "^3.23.1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.244", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.244.tgz", + "integrity": "sha512-OszpBN7xZX4vWMPJwB9illkN/znA8M36GQqQxi6MNy9axWxhOfJyZZJtSLQCpEFLHP2xK33BiWx9aIuIEXVCcw==", + "dev": true, + "license": "ISC" + }, + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/engine.io": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", + "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", + "license": "MIT", + "dependencies": { + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.7.2", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "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/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": "30.2.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/fast-check": { + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", + "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "dependencies": { + "pure-rand": "^6.1.0" + }, + "engines": { + "node": ">=8.0.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, + "license": "MIT" + }, + "node_modules/fast-xml-parser": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", + "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^2.1.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/giget": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", + "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.0", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.6", + "nypm": "^0.6.0", + "pathe": "^2.0.3" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "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/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, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "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, + "license": "ISC" + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-status": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-status/-/http-status-2.1.0.tgz", + "integrity": "sha512-O5kPr7AW7wYd/BBiOezTwnVAnmSNFY+J7hlZD2X5IOxVBetjcHAiTXhzj0gMrnojQlwy+UT1/Y3H3vJ3UlmvLA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "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==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "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, + "license": "BSD-3-Clause", + "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, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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-changed-files/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-changed-files/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, + "license": "MIT", + "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/jest-changed-files/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, + "license": "MIT" + }, + "node_modules/jest-changed-files/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-changed-files/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, + "license": "MIT", + "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-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, + "license": "MIT", + "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-circus/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/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, + "license": "MIT", + "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/jest-circus/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, + "license": "MIT" + }, + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-circus/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-circus/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, + "license": "MIT", + "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-circus/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, + "license": "MIT", + "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-circus/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, + "license": "MIT", + "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-circus/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, + "license": "MIT", + "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-circus/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, + "license": "MIT", + "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/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, + "license": "MIT", + "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-cli/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli/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, + "license": "MIT", + "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/jest-cli/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, + "license": "MIT" + }, + "node_modules/jest-cli/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/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, + "license": "MIT", + "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-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, + "license": "MIT", + "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/@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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-config/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, + "license": "MIT", + "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-config/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, + "license": "MIT", + "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/jest-config/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/jest-config/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, + "license": "MIT" + }, + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-config/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, + "license": "MIT", + "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/jest-config/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/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, + "license": "MIT", + "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/jest-config/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, + "license": "MIT", + "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/jest-config/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/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, + "license": "MIT", + "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-config/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, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-config/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, + "license": "MIT", + "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-config/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, + "license": "MIT", + "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-config/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, + "license": "MIT", + "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/jest-config/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/jest-config/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, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-config/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/jest-diff": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", + "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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, + "license": "MIT", + "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, + "license": "MIT", + "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-each/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each/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, + "license": "MIT", + "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/jest-each/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, + "license": "MIT" + }, + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-each/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-each/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, + "license": "MIT", + "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-each/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, + "license": "MIT", + "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/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, + "license": "MIT", + "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-environment-node/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node/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, + "license": "MIT", + "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/jest-environment-node/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, + "license": "MIT" + }, + "node_modules/jest-environment-node/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-node/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, + "license": "MIT", + "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-environment-node/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, + "license": "MIT", + "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-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, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz", + "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.2.0", + "jest-worker": "30.2.0", + "micromatch": "^4.0.8", + "walker": "^1.0.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.3" + } + }, + "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, + "license": "MIT", + "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-leak-detector/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-leak-detector/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, + "license": "MIT" + }, + "node_modules/jest-leak-detector/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-leak-detector/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, + "license": "MIT", + "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/jest-matcher-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", + "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "jest-diff": "30.2.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", + "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.2.0", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-mock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", + "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-util": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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, + "license": "MIT", + "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, + "license": "MIT", + "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-resolve-dependencies/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, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve/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, + "license": "MIT", + "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/jest-resolve/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, + "license": "MIT" + }, + "node_modules/jest-resolve/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-resolve/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, + "license": "MIT", + "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-resolve/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, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve/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, + "license": "MIT", + "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-resolve/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, + "license": "MIT", + "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-resolve/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "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, + "license": "MIT", + "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/@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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/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, + "license": "MIT", + "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-runner/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, + "license": "MIT", + "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/jest-runner/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/jest-runner/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, + "license": "MIT" + }, + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner/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, + "license": "MIT", + "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-runner/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, + "license": "MIT", + "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-runner/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, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/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, + "license": "MIT", + "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-runner/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, + "license": "MIT", + "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-runner/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, + "license": "MIT", + "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/jest-runner/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-runner/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.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, + "license": "MIT", + "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/@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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/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, + "license": "MIT", + "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-runtime/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, + "license": "MIT", + "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/jest-runtime/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/jest-runtime/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, + "license": "MIT" + }, + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/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, + "license": "MIT", + "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-runtime/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, + "license": "MIT", + "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-runtime/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, + "license": "MIT", + "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-runtime/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, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/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, + "license": "MIT", + "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-runtime/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, + "license": "MIT", + "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-runtime/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, + "license": "MIT", + "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/jest-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/jest-runtime/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "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, + "license": "MIT", + "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-snapshot/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, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/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, + "license": "MIT", + "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-snapshot/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, + "license": "MIT", + "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/jest-snapshot/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/jest-snapshot/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, + "license": "MIT" + }, + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot/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, + "license": "MIT", + "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/jest-snapshot/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot/node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/jest-snapshot/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, + "license": "MIT", + "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-snapshot/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, + "license": "MIT", + "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-snapshot/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, + "license": "MIT", + "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-snapshot/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, + "license": "MIT", + "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-snapshot/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, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/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, + "license": "MIT", + "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-snapshot/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, + "license": "MIT", + "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-snapshot/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, + "license": "MIT", + "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/jest-snapshot/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/jest-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", + "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-util/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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, + "license": "MIT", + "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/@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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/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, + "license": "MIT", + "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/jest-validate/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, + "license": "MIT" + }, + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-validate/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, + "license": "MIT", + "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/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, + "license": "MIT", + "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-watcher/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watcher/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, + "license": "MIT", + "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/jest-watcher/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, + "license": "MIT" + }, + "node_modules/jest-watcher/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher/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, + "license": "MIT", + "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-worker": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.2.0.tgz", + "integrity": "sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.2.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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, + "license": "MIT", + "optional": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jest/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest/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, + "license": "MIT", + "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/jest/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, + "license": "MIT" + }, + "node_modules/jiti": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", + "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "devOptional": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/jmespath": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.6.0" + } + }, + "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, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "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, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=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==", + "license": "MIT", + "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.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/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, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/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, + "license": "MIT", + "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, + "license": "ISC" + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/multer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", + "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", + "object-assign": "^4.1.1", + "type-is": "^1.6.18", + "xtend": "^4.0.2" + }, + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/multer-s3": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/multer-s3/-/multer-s3-3.0.1.tgz", + "integrity": "sha512-BFwSO80a5EW4GJRBdUuSHblz2jhVSAze33ZbnGpcfEicoT0iRolx4kWR+AJV07THFRCQ78g+kelKFdjkCCaXeQ==", + "license": "MIT", + "dependencies": { + "@aws-sdk/lib-storage": "^3.46.0", + "file-type": "^3.3.0", + "html-comment-regex": "^1.1.2", + "run-parallel": "^1.1.6" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-s3": "^3.0.0" + } + }, + "node_modules/multer/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "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, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz", + "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "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, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nypm": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.1.tgz", + "integrity": "sha512-hlacBiRiv1k9hZFiphPUkfSQ/ZfQzZDzC+8z0wL3lvDAOUu/2NnChkKuMoMjNur/9OpKuz2QsIeiPVN0xM5Q0w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.2", + "pathe": "^2.0.3", + "pkg-types": "^2.2.0", + "tinyexec": "^1.0.1" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "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==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "license": "MIT", + "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-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", + "license": "MIT", + "dependencies": { + "jsonwebtoken": "^9.0.0", + "passport-strategy": "^1.0.0" + } + }, + "node_modules/passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/pretty-format": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prisma": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.15.0.tgz", + "integrity": "sha512-E6RCgOt+kUVtjtZgLQDBJ6md2tDItLJNExwI0XJeBc1FKL+Vwb+ovxXxuok9r8oBgsOXBA33fGDuE/0qDdCWqQ==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@prisma/config": "6.15.0", + "@prisma/engines": "6.15.0" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "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==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", + "license": "MIT" + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc9": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", + "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "defu": "^6.1.4", + "destr": "^2.0.3" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "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, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "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" + } + ], + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==", + "license": "ISC" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "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==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "ISC" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/socket.io": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.6.0", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "license": "MIT", + "dependencies": { + "debug": "~4.3.4", + "ws": "~8.17.1" + } + }, + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-adapter/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/socket.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/socket.io/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/socket.io/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "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, + "license": "BSD-3-Clause" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "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.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strnum": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz", + "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "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==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tinyexec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", + "devOptional": true, + "license": "MIT" + }, + "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, + "license": "BSD-3-Clause" + }, + "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, + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-jest": { + "version": "29.4.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.5.tgz", + "integrity": "sha512-HO3GyiWn2qvTQA4kTgjDcXiMwYQt68a1Y8+JuLRVpdIzm+UOLSHgl/XqR4c6nzJkq5rOkjc02O2I7P7l/Yof0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.7.3", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jest-util": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "peer": 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/ts-node-dev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz", + "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.1", + "dynamic-dedupe": "^0.3.0", + "minimist": "^1.2.6", + "mkdirp": "^1.0.4", + "resolve": "^1.0.0", + "rimraf": "^2.6.1", + "source-map-support": "^0.5.12", + "tree-kill": "^1.2.2", + "ts-node": "^10.4.0", + "tsconfig": "^7.0.0" + }, + "bin": { + "ts-node-dev": "lib/bin.js", + "tsnd": "lib/bin.js" + }, + "engines": { + "node": ">=0.8.0" + }, + "peerDependencies": { + "node-notifier": "*", + "typescript": "*" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/ts-node-dev/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "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" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/ts-node-dev/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-node-dev/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/tsconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", + "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/strip-bom": "^3.0.0", + "@types/strip-json-comments": "0.0.30", + "strip-bom": "^3.0.0", + "strip-json-comments": "^2.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.20.5", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.5.tgz", + "integrity": "sha512-+wKjMNU9w/EaQayHXb7WA7ZaHY6hN8WgfvHNQ3t1PnU91/7O8TcTnIhCDYTZwnt8JsO9IBqZ30Ln1r7pPF52Aw==", + "license": "MIT", + "dependencies": { + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "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==", + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/undici-types": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", + "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" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", + "license": "MIT", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "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/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "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==", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/write-file-atomic/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, + "license": "ISC", + "optional": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "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, + "license": "MIT", + "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, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.0.14.tgz", + "integrity": "sha512-nGFJTnJN6cM2v9kXL+SOBq3AtjQby3Mv5ySGFof5UGRHrRioSJ5iG680cYNjE/yWk671nROcpPj4hAS8nyLhSw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/mission 10/package.json b/mission 10/package.json new file mode 100644 index 000000000..53cfc0bac --- /dev/null +++ b/mission 10/package.json @@ -0,0 +1,61 @@ +{ + "name": "mission3", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "dev": "ts-node --files src/app.ts", + "start": "node dist/app.js", + "lint": "eslint . --ext .ts", + "prisma:generate": "prisma generate", + "prisma:migrate": "prisma migrate dev", + "test": "jest --coverage", + "test:watch": "jest --watch" + }, + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "@prisma/client": "^6.13.0", + "aws-sdk": "^2.1692.0", + "bcrypt": "^6.0.0", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^17.2.2", + "express": "^5.1.0", + "http-status": "^2.1.0", + "multer": "^2.0.2", + "multer-s3": "^3.0.1", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", + "passport-local": "^1.0.0", + "socket.io": "^4.8.1", + "tsx": "^4.20.5", + "ws": "^8.18.3", + "zod": "^4.0.14" + }, + "devDependencies": { + "@types/aws-sdk": "^0.0.42", + "@types/bcrypt": "^6.0.0", + "@types/cookie-parser": "^1.4.9", + "@types/cors": "^2.8.19", + "@types/express": "^5.0.3", + "@types/jest": "^30.0.0", + "@types/jsonwebtoken": "^9.0.10", + "@types/multer": "^2.0.0", + "@types/multer-s3": "^3.0.3", + "@types/node": "^24.3.1", + "@types/passport": "^1.0.17", + "@types/passport-jwt": "^4.0.1", + "@types/passport-local": "^1.0.38", + "@types/uuid": "^10.0.0", + "jest": "^29.7.0", + "prisma": "^6.15.0", + "ts-jest": "^29.4.5", + "ts-node": "^10.9.2", + "ts-node-dev": "^2.0.0", + "typescript": "^5.9.3" + }, + "prisma": { + "seed": "node prisma/seed.js" + } +} diff --git a/mission 10/prisma/migrations/20250904083711_test/migration.sql b/mission 10/prisma/migrations/20250904083711_test/migration.sql new file mode 100644 index 000000000..ad7fbdc5d --- /dev/null +++ b/mission 10/prisma/migrations/20250904083711_test/migration.sql @@ -0,0 +1,94 @@ +-- CreateTable +CREATE TABLE "public"."User" ( + "id" SERIAL NOT NULL, + "email" TEXT NOT NULL, + "nickname" TEXT NOT NULL, + "image" TEXT, + "password" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Product" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT NOT NULL, + "price" INTEGER NOT NULL, + "tags" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Product_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Article" ( + "id" SERIAL NOT NULL, + "title" TEXT NOT NULL, + "content" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Article_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Comment" ( + "id" SERIAL NOT NULL, + "content" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "productId" INTEGER, + "articleId" INTEGER, + "userId" INTEGER NOT NULL, + + CONSTRAINT "Comment_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Like" ( + "id" SERIAL NOT NULL, + "like" BOOLEAN NOT NULL DEFAULT true, + "userId" INTEGER NOT NULL, + "productId" INTEGER, + "articleId" INTEGER, + + CONSTRAINT "Like_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "public"."User"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "Like_userId_productId_key" ON "public"."Like"("userId", "productId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Like_userId_articleId_key" ON "public"."Like"("userId", "articleId"); + +-- AddForeignKey +ALTER TABLE "public"."Product" ADD CONSTRAINT "Product_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Article" ADD CONSTRAINT "Article_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_productId_fkey" FOREIGN KEY ("productId") REFERENCES "public"."Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "public"."Article"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_productId_fkey" FOREIGN KEY ("productId") REFERENCES "public"."Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Like" ADD CONSTRAINT "Like_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "public"."Article"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/mission 10/prisma/migrations/20251031084424_init/migration.sql b/mission 10/prisma/migrations/20251031084424_init/migration.sql new file mode 100644 index 000000000..2827ddec8 --- /dev/null +++ b/mission 10/prisma/migrations/20251031084424_init/migration.sql @@ -0,0 +1,14 @@ +-- CreateTable +CREATE TABLE "public"."Alert" ( + "id" SERIAL NOT NULL, + "userId" INTEGER NOT NULL, + "message" TEXT NOT NULL, + "link" TEXT, + "isRead" BOOLEAN NOT NULL DEFAULT false, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Alert_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "public"."Alert" ADD CONSTRAINT "Alert_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/mission 10/prisma/migrations/migration_lock.toml b/mission 10/prisma/migrations/migration_lock.toml new file mode 100644 index 000000000..044d57cdb --- /dev/null +++ b/mission 10/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (e.g., Git) +provider = "postgresql" diff --git a/mission 10/prisma/schema.prisma b/mission 10/prisma/schema.prisma new file mode 100644 index 000000000..a43c08252 --- /dev/null +++ b/mission 10/prisma/schema.prisma @@ -0,0 +1,87 @@ +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" +} + +model User { + id Int @id @default(autoincrement()) + email String @unique + nickname String + image String? + password String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + article Article[] + product Product[] + comment Comment[] + like Like[] + alert Alert[] +} + +model Product { + id Int @id @default(autoincrement()) + name String + description String + price Int + tags String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + comment Comment[] + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + like Like[] +} + +model Article { + id Int @id @default(autoincrement()) + title String + content String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + comment Comment[] + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + like Like[] +} + +model Comment { + id Int @id @default(autoincrement()) + content String + createdAt DateTime @default(now()) + productId Int? + product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) + articleId Int? + article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) +} + +model Like { + id Int @id @default(autoincrement()) + like Boolean @default(true) + userId Int + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + productId Int? + product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) + articleId Int? + article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) + + // 유저-상품, 유저-게시글 각각 중복 방지, 좋아요 중첩 방지 + @@unique([userId, productId]) + @@unique([userId, articleId]) +} + +model Alert { + id Int @id @default(autoincrement()) + userId Int + message String + link String? + isRead Boolean @default(false) + createdAt DateTime @default(now()) + + user User @relation(fields: [userId], references: [id]) +} \ No newline at end of file diff --git a/mission 10/src/app.ts b/mission 10/src/app.ts new file mode 100644 index 000000000..2e22575ff --- /dev/null +++ b/mission 10/src/app.ts @@ -0,0 +1,39 @@ +import express from "express"; +import cookieParser from "cookie-parser"; +import router from "./routers/index"; +import passport from "./lib/passport/index"; +import cors from "cors"; +import { errorHandler } from "./middlewares/errorHandler"; +import http from "http"; +import { initIo } from "./socket/io"; // ⬅ io 초기화 함수만 import +import { registerSocket } from "./socket/socket"; // ⬅ 소켓 이벤트 등록 + +const app = express(); + +app.use(express.urlencoded({ extended: true })); +app.use(express.json()); +app.use(cookieParser()); + +const corsOptions = { + origin: "http://localhost:3000", + optionsSuccessStatus: 200, + credentials: true, +}; +app.use(cors(corsOptions)); + +app.use(passport.initialize()); +app.use(router); + +app.use(errorHandler); + +const server = http.createServer(app); + +initIo(server); +registerSocket(); + +// server.listen(PORT, () => { +// console.log(`Server is running on http://localhost:${PORT}`); +// }); + +export { app, server }; +export default app; \ No newline at end of file diff --git a/mission 10/src/controllers/alertController.ts b/mission 10/src/controllers/alertController.ts new file mode 100644 index 000000000..058502c17 --- /dev/null +++ b/mission 10/src/controllers/alertController.ts @@ -0,0 +1,36 @@ +import { Request, Response } from "express"; +import { AlertService } from "../services/alertService"; +import status from "http-status"; + +export class AlertController { + private service = new AlertService(); + + list = async (req: Request, res: Response) => { + if (!req.user) + return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const userId = req.user.id; + const alerts = await this.service.list(userId); + res.json(alerts); + }; + + markAsRead = async (req: Request, res: Response) => { + if (!req.user) + return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const userId = req.user.id; + const alertId = Number(req.params.id); + + if (!alertId) { + throw new Error("Article not found"); + } + + const success = await this.service.read(alertId, userId); + + if (!success) { + return res.status(status.FORBIDDEN).json({ + message: "You do not have permission to read this alert", + }); + } + res.status(204).send(); + }; +} diff --git a/mission 10/src/controllers/articleController.ts b/mission 10/src/controllers/articleController.ts new file mode 100644 index 000000000..b68458542 --- /dev/null +++ b/mission 10/src/controllers/articleController.ts @@ -0,0 +1,70 @@ +import { Request, Response, NextFunction } from "express"; +import status from "http-status"; +import { ArticleService } from "../services/articleService"; +import { ArticleCreateSchema, ArticleUpdateSchema, ArticleQuerySchema } from "../dtos/article.dto"; + +const articleService = new ArticleService(); + +export class ArticleController { + async create(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const parsed = ArticleCreateSchema.parse(req.body); + const article = await articleService.create(req.user.id, parsed); + res.status(status.CREATED).json(article); + } catch (err) { + next(err); + } + } + + async list(req: Request, res: Response, next: NextFunction) { + try { + const parsed = ArticleQuerySchema.parse(req.query); + const articles = await articleService.list(parsed); + res.status(status.OK).json(articles); + } catch (err) { + next(err); + } + } + + async detail(req: Request, res: Response, next: NextFunction) { + try { + const articleId = Number(req.params.id); + const article = await articleService.getDetail(articleId); + if (!article) return res.status(status.NOT_FOUND).json({ message: "Article not found" }); + res.status(status.OK).json(article); + } catch (err) { + next(err); + } + } + + async update(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = ArticleUpdateSchema.parse(req.body) as { title?: string; content?: string; }; + const articleId = Number(req.params.id); + const updated = await articleService.update(req.user.id, parsed, articleId); + + res.status(status.OK).json(updated); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + + async delete(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const articleId = Number(req.params.id); + await articleService.delete(req.user.id, articleId); + res.status(status.NO_CONTENT).end(); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } +} diff --git a/mission 10/src/controllers/commentController.ts b/mission 10/src/controllers/commentController.ts new file mode 100644 index 000000000..ec81a315f --- /dev/null +++ b/mission 10/src/controllers/commentController.ts @@ -0,0 +1,88 @@ +import { Request, Response, NextFunction } from "express"; +import { z } from "zod"; +import status from "http-status"; +import { CommentService } from "../services/commentService"; + +const commentService = new CommentService(); + +const commentSchema = z.object({ + content: z.string().min(5).max(100), +}); + +const commentListSchema = z.object({ + id: z.coerce.number().int().positive(), + lastId: z.coerce.number().int().positive().optional(), +}); + +export class CommentController { + async createProductComment(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const productId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const comment = await commentService.createProductComment(req.user.id, productId, parsed.content); + res.status(status.CREATED).json(comment); + } catch (err) { + next(err); + } + } + + async createArticleComment(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const articleId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const comment = await commentService.createArticleComment(req.user.id, articleId, parsed.content); + res.status(status.CREATED).json(comment); + } catch (err) { + next(err); + } + } + + async modifyComment(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const commentId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const updated = await commentService.updateComment(req.user.id, commentId, parsed.content); + res.status(status.OK).json(updated); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Comment not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + + async deleteComment(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const commentId = Number(req.params.id); + await commentService.deleteComment(req.user.id, commentId); + res.status(status.NO_CONTENT).end(); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Comment not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + + async productCommentList(req: Request, res: Response, next: NextFunction) { + try { + const parsed = commentListSchema.parse({ id: req.params.id, lastId: req.query.lastId }); + const comments = await commentService.getProductComments(parsed.id, parsed.lastId); + res.status(status.OK).json(comments); + } catch (err) { + next(err); + } + } + + async articleCommentList(req: Request, res: Response, next: NextFunction) { + try { + const parsed = commentListSchema.parse({ id: req.params.id, lastId: req.query.lastId }); + const comments = await commentService.getArticleComments(parsed.id, parsed.lastId); + res.status(status.OK).json(comments); + } catch (err) { + next(err); + } + } +} \ No newline at end of file diff --git a/mission 10/src/controllers/likeController.ts b/mission 10/src/controllers/likeController.ts new file mode 100644 index 000000000..5e4c1edba --- /dev/null +++ b/mission 10/src/controllers/likeController.ts @@ -0,0 +1,51 @@ +import { Request, Response, NextFunction } from "express"; +import status from "http-status"; +import { LikeService } from "../services/likeService"; + +const likeService = new LikeService(); + +export class LikeController { + async likeArticle(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const result = await likeService.likeArticle(req.user.id, Number(req.params.id)); + res.status(status.OK).json({ message: "Like toggled", isLiked: result.like }); + } catch (err: any) { + if (err.message === "ARTICLE_NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Article not found" }); + next(err); + } + } + + async likeProduct(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const result = await likeService.likeProduct(req.user.id, Number(req.params.id)); + res.status(status.OK).json({ message: "Like toggled", isLiked: result.like }); + } catch (err: any) { + if (err.message === "PRODUCT_NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + next(err); + } + } + + async getLikedArticles(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const likedArticles = await likeService.getLikedArticles(req.user.id); + const articles = likedArticles.map((l) => ({ ...l.article, isLiked: true })); + res.status(status.OK).json(articles); + } catch (err) { + next(err); + } + } + + async getLikedProducts(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const likedProducts = await likeService.getLikedProducts(req.user.id); + const products = likedProducts.map((l) => ({ ...l.product, isLiked: true })); + res.status(status.OK).json(products); + } catch (err) { + next(err); + } + } +} \ No newline at end of file diff --git a/mission 10/src/controllers/photoController.ts b/mission 10/src/controllers/photoController.ts new file mode 100644 index 000000000..cf3e9cc9f --- /dev/null +++ b/mission 10/src/controllers/photoController.ts @@ -0,0 +1,29 @@ +import { Request, Response, NextFunction } from "express"; +import prisma from "../lib/prisma"; +import status from "http-status"; + +export class PhotoController { + async upload(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(401).json({ message: "Unauthorized" }); + + if (!req.file) { + return res.status(status.BAD_REQUEST).json({ message: "No file uploaded" }); + } + + try { + const imageUrl = (req.file as any).location; + + const updatedUser = await prisma.user.update({ + where: { id: req.user.id }, + data: { image: imageUrl }, + }); + + res.status(status.OK).json({ + message: "Photo uploaded successfully", + image: updatedUser.image, + }); + } catch (err) { + next(err); + } + } +} \ No newline at end of file diff --git a/mission 10/src/controllers/productController.ts b/mission 10/src/controllers/productController.ts new file mode 100644 index 000000000..5d42d09b9 --- /dev/null +++ b/mission 10/src/controllers/productController.ts @@ -0,0 +1,68 @@ +import { Request, Response, NextFunction } from "express"; +import status from "http-status"; +import { ProductService } from "../services/productService"; +import { ProductCreateSchema, ProductUpdateSchema, ProductQuerySchema } from "../dtos/product.dto"; + +const productService = new ProductService(); + +export class ProductController { + async create(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = ProductCreateSchema.parse(req.body); + const product = await productService.create(req.user.id, parsed); + res.status(status.CREATED).json(product); + } catch (err) { + next(err); + } + } + + async list(req: Request, res: Response, next: NextFunction) { + try { + const parsed = ProductQuerySchema.parse(req.query); + const products = await productService.list(parsed); + res.status(status.OK).json(products); + } catch (err) { + next(err); + } + } + + async detail(req: Request, res: Response, next: NextFunction) { + try { + const productId = Number(req.params.id); + const product = await productService.getDetail(productId); + if (!product) return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + res.status(status.OK).json(product); + } catch (err) { + next(err); + } + } + + async update(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = ProductUpdateSchema.parse(req.body) as { name?: string; description?: string; price?: number; tags?: string; }; + const productId = Number(req.params.id); + const updated = await productService.update(req.user.id, productId, parsed); + + res.status(status.OK).json(updated); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + + async delete(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const productId = Number(req.params.id); + await productService.delete(req.user.id, productId); + res.status(status.NO_CONTENT).end(); + } catch (err: any) { + if (err.message === "NOT_FOUND") return res.status(status.NOT_FOUND).json({ message: "Product not found" }); + if (err.message === "FORBIDDEN") return res.status(status.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } +} \ No newline at end of file diff --git a/mission 10/src/controllers/userController.ts b/mission 10/src/controllers/userController.ts new file mode 100644 index 000000000..e6c61a7ac --- /dev/null +++ b/mission 10/src/controllers/userController.ts @@ -0,0 +1,97 @@ +import { Request, Response, NextFunction } from "express"; +import status from "http-status"; +import { UserService } from "../services/userService"; +import { setTokenCookies, clearTokenCookies } from "../lib/cookieUtil"; +import { UserRegisterSchema, UserUpdateSchema, UserPasswordSchema, UserLoginSchema } from "../dtos/user.dto"; + +const userService = new UserService(); + +export class UserController { + async register(req: Request, res: Response, next: NextFunction) { + try { + const parsed = UserRegisterSchema.parse(req.body); + const result = await userService.register(parsed); + res.status(status.CREATED).json(result); + } catch (err: any) { + if (err.message === "EMAIL_EXISTS") { + return res.status(status.CONFLICT).json({ message: "This ID already exists" }); + } + next(err); + } + } + + login(req: Request, res: Response, next: NextFunction) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + try { + const { accessToken, refreshToken } = userService.generateUserTokens(req.user.id); + setTokenCookies(res, accessToken, refreshToken); + + res.status(status.OK).json({ accessToken, refreshToken }); + } catch (err) { + next(err); + } + } + + async profile(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const profile = await userService.getProfile(req.user.id); + res.status(status.OK).json(profile); + } catch (err) { + next(err); + } + } + + async modifyInformation(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const parsed = UserUpdateSchema.parse(req.body); // DTO 검증 + const updatedUser = await userService.updateInformation(req.user.id, parsed.nickname, parsed.image); + + res.status(status.OK).json({ message: "User information updated successfully", user: updatedUser }); + } catch (err: any) { + if (err.message === "NO_DATA") return res.status(status.BAD_REQUEST).json({ message: "No update data provided" }); + next(err); + } + } + + async modifyPassword(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + + const parsed = UserPasswordSchema.parse(req.body); // DTO 검증 + const result = await userService.updatePassword(req.user.id, parsed); + + res.status(status.OK).json(result); + } catch (err) { + next(err); + } + } + + async products(req: Request, res: Response, next: NextFunction) { + try { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const products = await userService.getProducts(req.user.id); + if (!products || products.length === 0) { + return res.status(status.NOT_FOUND).json({ message: "No product" }); + } + res.status(status.OK).json(products); + } catch (err) { + next(err); + } + } + + refreshTokens(req: Request, res: Response) { + if (!req.user) return res.status(status.UNAUTHORIZED).json({ message: "Unauthorized" }); + const { accessToken, refreshToken } = userService.generateUserTokens(req.user.id); + setTokenCookies(res, accessToken, refreshToken); + res.status(status.OK).send({ message: "Tokens refreshed" }); + } + + logout(req: Request, res: Response) { + clearTokenCookies(res); + res.status(status.OK).send({ message: "Logged out successfully" }); + } +} diff --git a/mission 10/src/dtos/article.dto.ts b/mission 10/src/dtos/article.dto.ts new file mode 100644 index 000000000..c6709cf00 --- /dev/null +++ b/mission 10/src/dtos/article.dto.ts @@ -0,0 +1,38 @@ +import { z } from "zod"; + +// CREATE DTO +export const ArticleCreateSchema = z.object({ + title: z.string().min(1, { message: "제목을 입력해주세요" }), + content: z + .string() + .min(10, { message: "내용은 최소 10자 이상이어야 합니다." }) + .max(200, { message: "내용은 최대 200자까지 가능합니다." }), +}); +export type ArticleCreateDTO = z.infer; + +// UPDATE DTO (PATCH) +export const ArticleUpdateSchema = z.object({ + title: z.string().min(1, { message: "제목을 입력해주세요" }).optional(), + content: z + .string() + .min(10, { message: "내용은 최소 10자 이상이어야 합니다." }) + .max(200, { message: "내용은 최대 200자까지 가능합니다." }) + .optional(), +}); +export type ArticleUpdateDTO = z.infer; + +// QUERY DTO (GET /articles) +export const ArticleQuerySchema = z.object({ + page: z + .string() + .default("1") + .transform(Number) + .refine((val) => val > 0, { message: "page는 1 이상의 정수여야 합니다." }), + pageSize: z + .string() + .default("5") + .transform(Number) + .refine((val) => val > 0 && val <= 100, { message: "pageSize는 1~100 사이여야 합니다." }), + keyword: z.string().default(""), +}); +export type ArticleQueryDTO = z.infer; diff --git a/mission 10/src/dtos/product.dto.ts b/mission 10/src/dtos/product.dto.ts new file mode 100644 index 000000000..edac3858a --- /dev/null +++ b/mission 10/src/dtos/product.dto.ts @@ -0,0 +1,28 @@ +import { z } from "zod"; + + +// CREATE DTO +export const ProductCreateSchema = z.object({ + name: z.string().min(1, { message: "이름을 입력해주세요" }), + description: z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }), + price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }), + tags: z.string().default(""), +}); +export type ProductCreateDTO = z.infer; + +// UPDATE DTO +export const ProductUpdateSchema = z.object({ + name: z.string().min(1, { message: "이름을 입력해주세요" }).optional(), + description: z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }).optional(), + price: z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }).optional(), + tags: z.string().default("").optional(), +}); +export type ProductUpdateDTO = z.infer; + +// QUERY DTO +export const ProductQuerySchema = z.object({ + page: z.string().default("1").transform(Number).refine((v) => v > 0), + pageSize: z.string().default("5").transform(Number).refine((v) => v > 0 && v <= 100), + keyword: z.string().default(""), +}); +export type ProductQueryDTO = z.infer; \ No newline at end of file diff --git a/mission 10/src/dtos/user.dto.ts b/mission 10/src/dtos/user.dto.ts new file mode 100644 index 000000000..1bed9d74a --- /dev/null +++ b/mission 10/src/dtos/user.dto.ts @@ -0,0 +1,29 @@ +import { z } from "zod"; + +// 회원가입 +export const UserRegisterSchema = z.object({ + email: z.string().email({ message: "Invalid email" }), + nickname: z.string().min(2, { message: "Nickname too short" }), + password: z.string().min(6, { message: "Password too short" }), +}); +export type UserRegisterDTO = z.infer; + +// 로그인 +export const UserLoginSchema = z.object({ + email: z.string().email(), + password: z.string().min(6), +}); +export type UserLoginDTO = z.infer; + +// 정보 수정 (PATCH) +export const UserUpdateSchema = z.object({ + nickname: z.string().min(2).optional(), + image: z.string().url().optional(), +}); +export type UserUpdateDTO = z.infer; + +// 비밀번호 수정 +export const UserPasswordSchema = z.object({ + password: z.string().min(6, { message: "Password too short" }), +}); +export type UserPasswordDTO = z.infer; diff --git a/mission 10/src/lib/constants.ts b/mission 10/src/lib/constants.ts new file mode 100644 index 000000000..af8e48a99 --- /dev/null +++ b/mission 10/src/lib/constants.ts @@ -0,0 +1,21 @@ +import dotenv from 'dotenv'; + +dotenv.config(); + +const NODE_ENV = process.env.NODE_ENV || 'development'; +const PORT = process.env.PORT || 3000; +const JWT_ACCESS_TOKEN_SECRET = + process.env.JWT_ACCESS_TOKEN_SECRET || 'your_jwt_access_token_secret'; +const JWT_REFRESH_TOKEN_SECRET = + process.env.JWT_REFRESH_TOKEN_SECRET || 'your_jwt_refresh_token_secret'; +const ACCESS_TOKEN_COOKIE_NAME = 'access-token'; +const REFRESH_TOKEN_COOKIE_NAME = 'refresh-token'; + +export { + NODE_ENV, + PORT, + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, + ACCESS_TOKEN_COOKIE_NAME, + REFRESH_TOKEN_COOKIE_NAME, +}; diff --git a/mission 10/src/lib/cookieUtil.ts b/mission 10/src/lib/cookieUtil.ts new file mode 100644 index 000000000..6d50ff83d --- /dev/null +++ b/mission 10/src/lib/cookieUtil.ts @@ -0,0 +1,22 @@ +import { Response } from "express"; +import { ACCESS_TOKEN_COOKIE_NAME, REFRESH_TOKEN_COOKIE_NAME, NODE_ENV } from "./constants"; + +export function setTokenCookies(res: Response, accessToken: string, refreshToken: string) { + res.cookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, { + httpOnly: true, + secure: NODE_ENV === "production", + maxAge: 1 * 60 * 60 * 1000, // 1시간 + }); + + res.cookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken, { + httpOnly: true, + secure: NODE_ENV === "production", + maxAge: 7 * 24 * 60 * 60 * 1000, // 7일 + path: "/users/refresh", + }); +} + +export function clearTokenCookies(res: Response) { + res.clearCookie(ACCESS_TOKEN_COOKIE_NAME); + res.clearCookie(REFRESH_TOKEN_COOKIE_NAME); +} diff --git a/mission 10/src/lib/passport/index.ts b/mission 10/src/lib/passport/index.ts new file mode 100644 index 000000000..771eb1518 --- /dev/null +++ b/mission 10/src/lib/passport/index.ts @@ -0,0 +1,9 @@ +import passport from 'passport'; +import { localStrategy } from './localStrategy'; +import { accessTokenStrategy, refreshTokenStrategy } from './jwtStrategy'; + +passport.use('local', localStrategy); +passport.use('access-token', accessTokenStrategy); +passport.use('refresh-token', refreshTokenStrategy); + +export default passport; diff --git a/mission 10/src/lib/passport/jwtStrategy.ts b/mission 10/src/lib/passport/jwtStrategy.ts new file mode 100644 index 000000000..3561a8013 --- /dev/null +++ b/mission 10/src/lib/passport/jwtStrategy.ts @@ -0,0 +1,52 @@ +import { Strategy as JwtStrategy, ExtractJwt } from 'passport-jwt'; +import prisma from '../prisma'; +import type { Request } from 'express'; +import type { VerifiedCallback } from 'passport-jwt'; +import { + ACCESS_TOKEN_COOKIE_NAME, + REFRESH_TOKEN_COOKIE_NAME, + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, +} from '../constants'; + +interface JwtPayload { + sub: number; +} + +// const accessTokenOptions = { +// jwtFromRequest: (req: Request) => req.cookies[ACCESS_TOKEN_COOKIE_NAME], +// secretOrKey: JWT_ACCESS_TOKEN_SECRET, +// }; + +const accessTokenOptions = { + jwtFromRequest: (req: Request) => { + return req.cookies[ACCESS_TOKEN_COOKIE_NAME] || ExtractJwt.fromAuthHeaderAsBearerToken()(req); + }, + secretOrKey: JWT_ACCESS_TOKEN_SECRET, +}; + +const refreshTokenOptions = { + jwtFromRequest: (req: Request) => req.cookies[REFRESH_TOKEN_COOKIE_NAME], + secretOrKey: JWT_REFRESH_TOKEN_SECRET, +}; + +async function jwtVerify(payload: JwtPayload, done: VerifiedCallback) { + try { + const user = await prisma.user.findUnique({ + where: { id: payload.sub }, + }); + done(null, user); + } catch (error) { + done(error, false); + } +} + +export const accessTokenStrategy = new JwtStrategy( + accessTokenOptions, + jwtVerify +); + +export const refreshTokenStrategy = new JwtStrategy( + refreshTokenOptions, + jwtVerify +); diff --git a/mission 10/src/lib/passport/localStrategy.ts b/mission 10/src/lib/passport/localStrategy.ts new file mode 100644 index 000000000..3c3e7ba10 --- /dev/null +++ b/mission 10/src/lib/passport/localStrategy.ts @@ -0,0 +1,27 @@ +import { Strategy as LocalStrategy } from "passport-local"; +import bcrypt from "bcrypt"; +import prisma from "../prisma"; + +export const localStrategy = new LocalStrategy( + { + usernameField: "email", // email을 localStrategy의 고정값 'username' 대신 쓰도록 지정 + passwordField: "password", + }, + async (email, password, done) => { + try { + const user = await prisma.user.findUnique({ where: { email } }); + if (!user) { + return done(null, false, { message: "No user found" }); + } + + const isPasswordValid = await bcrypt.compare(password, user.password); + if (!isPasswordValid) { + return done(null, false, { message: "Invalid password" }); + } + + return done(null, user); + } catch (err) { + return done(err); + } + } +); diff --git a/mission 10/src/lib/prisma.ts b/mission 10/src/lib/prisma.ts new file mode 100644 index 000000000..b904402d2 --- /dev/null +++ b/mission 10/src/lib/prisma.ts @@ -0,0 +1,5 @@ +import { PrismaClient } from '@prisma/client'; + +const prisma = new PrismaClient(); + +export default prisma; \ No newline at end of file diff --git a/mission 10/src/lib/s3.ts b/mission 10/src/lib/s3.ts new file mode 100644 index 000000000..db307acd2 --- /dev/null +++ b/mission 10/src/lib/s3.ts @@ -0,0 +1,31 @@ +import { S3Client } from "@aws-sdk/client-s3"; +import multer from "multer"; +import multerS3 from "multer-s3"; +import { v4 as uuid } from "uuid"; + +// AWS.config.update({ +// region: process.env.AWS_REGION, +// accessKeyId: process.env.AWS_ACCESS_KEY_ID, +// secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, +// }); + +// const s3 = new AWS.S3({}); + +export const uploadS3 = multer({ + storage: multerS3({ + s3: new S3Client({ + credentials: { + accessKeyId: process.env.AWS_ACCESS_KEY_ID as string, + secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY as string, + }, + region: process.env.AWS_REGION, + }), + acl: "public-read-write", + bucket: process.env.AWS_S3_BUCKET!, + contentType: multerS3.AUTO_CONTENT_TYPE, + key: (req, file, cb) => { + const ext = file.originalname.split(".").pop(); + cb(null, `users/${uuid()}.${ext}`); + }, + }), +}); diff --git a/mission 10/src/lib/token.ts b/mission 10/src/lib/token.ts new file mode 100644 index 000000000..5bdb25906 --- /dev/null +++ b/mission 10/src/lib/token.ts @@ -0,0 +1,27 @@ + import jwt from 'jsonwebtoken'; +import { + JWT_ACCESS_TOKEN_SECRET, + JWT_REFRESH_TOKEN_SECRET, +} from './constants'; + +function generateTokens(userId: number) { + const accessToken = jwt.sign({ sub: userId }, JWT_ACCESS_TOKEN_SECRET, { + expiresIn: '1h', + }); + const refreshToken = jwt.sign({ sub: userId }, JWT_REFRESH_TOKEN_SECRET, { + expiresIn: '1d', + }); + return { accessToken, refreshToken }; +} + +function verifyAccessToken(token: string) { + const decoded = jwt.verify(token, JWT_ACCESS_TOKEN_SECRET); + return { userId: decoded.sub }; +} + +function verifyRefreshToken(token: string) { + const decoded = jwt.verify(token, JWT_REFRESH_TOKEN_SECRET); + return { userId: decoded.sub }; +} + +export { generateTokens, verifyAccessToken, verifyRefreshToken }; diff --git a/mission 10/src/middlewares/errorHandler.ts b/mission 10/src/middlewares/errorHandler.ts new file mode 100644 index 000000000..dcaa5aaf3 --- /dev/null +++ b/mission 10/src/middlewares/errorHandler.ts @@ -0,0 +1,22 @@ +import { z } from "zod"; +import httpStatus from "http-status"; +import express , { type Request, type Response, type NextFunction } from "express"; + +interface ExtendedError extends Error { + code?: string; +} + +export function errorHandler(err: ExtendedError, req: Request, res: Response, next: NextFunction) { + if (err instanceof z.ZodError) { + return res.status(httpStatus.BAD_REQUEST).json({ error: err.issues }); + } + + if (err.code === "P2025") { + return res.status(httpStatus.NOT_FOUND).json({ error: "Record not found" }); + } + + console.error("unhandled Error:", err); + return res + .status(httpStatus.INTERNAL_SERVER_ERROR) + .json({ error: "Internal Server Error" }); +} diff --git a/mission 10/src/repositories/alertRepository.ts b/mission 10/src/repositories/alertRepository.ts new file mode 100644 index 000000000..53fc4281c --- /dev/null +++ b/mission 10/src/repositories/alertRepository.ts @@ -0,0 +1,33 @@ +import prisma from "../lib/prisma"; + +export class AlertRepository { + async createAlert(data: { userId: number; message: string; link?: string }) { + return prisma.alert.create({ data }); + } + + async findByUserId(userId: number) { + return prisma.alert.findMany({ + where: { userId }, + orderBy: { createdAt: "desc" }, + }); + } + + async markAsRead(id: number) { + return prisma.alert.update({ + where: { id }, + data: { isRead: true }, + }); + } + + async countUnread(userId: number) { + return prisma.alert.count({ + where: { userId, isRead: false }, + }); + } + + async findById(id: number) { + return prisma.alert.findUnique({ + where: { id }, + }); + } +} diff --git a/mission 10/src/repositories/articleRepository.ts b/mission 10/src/repositories/articleRepository.ts new file mode 100644 index 000000000..815428ffb --- /dev/null +++ b/mission 10/src/repositories/articleRepository.ts @@ -0,0 +1,39 @@ +import prisma from "../lib/prisma"; +import { Prisma } from "@prisma/client"; + +export class ArticleRepository { + async createArticle(data: { userId: number; title: string; content: string }) { + return prisma.article.create({ data }); + } + + async findMany(where: Prisma.ArticleWhereInput, skip: number, take: number) { + return prisma.article.findMany({ + skip, + take, + orderBy: { createdAt: "desc" }, + select: { id: true, title: true, content: true, createdAt: true }, + where, + }); + } + + async findById(id: number) { + return prisma.article.findUnique({ + where: { id }, + select: { id: true, userId: true, title: true, content: true, createdAt: true }, + }); + } + + async updatedArticle(id: number, data: { title?: string; content?: string }) { + const updateData: { title?: string; content?: string } = {}; + if (data.title !== undefined) updateData.title = data.title; + if (data.content !== undefined) updateData.content = data.content; + + return prisma.article.update({ where: { id }, data: updateData }); + } + + async deleteArticle(id: number): Promise { + await prisma.article.delete({ where: { id } }); + } +} + +export default new ArticleRepository(); \ No newline at end of file diff --git a/mission 10/src/repositories/commentRepository.ts b/mission 10/src/repositories/commentRepository.ts new file mode 100644 index 000000000..38de775ae --- /dev/null +++ b/mission 10/src/repositories/commentRepository.ts @@ -0,0 +1,52 @@ +import prisma from "../lib/prisma"; + +export class CommentRepository { + async createProductComment(userId: number, productId: number, content: string) { + return prisma.comment.create({ + data: { content, productId, articleId: null, userId }, + }); + } + + async createArticleComment(userId: number, articleId: number, content: string) { + return prisma.comment.create({ + data: { content, productId: null, articleId, userId }, + }); + } + + async findById(commentId: number) { + return prisma.comment.findUnique({ where: { id: commentId } }); + } + + async updateComment(commentId: number, content: string) { + return prisma.comment.update({ + where: { id: commentId }, + data: { content }, + }); + } + + async deleteComment(commentId: number) { + return prisma.comment.delete({ where: { id: commentId } }); + } + + async findProductComments(productId: number, lastId?: number) { + return prisma.comment.findMany({ + where: { articleId: null, productId }, + take: 5, + skip: lastId ? 1 : 0, + ...(lastId && { cursor: { id: lastId } }), + select: { id: true, content: true, createdAt: true }, + }); + } + + async findArticleComments(articleId: number, lastId?: number) { + return prisma.comment.findMany({ + where: { articleId, productId: null }, + take: 5, + skip: lastId ? 1 : 0, + ...(lastId && { cursor: { id: lastId } }), + select: { id: true, content: true, createdAt: true }, + }); + } +} + +export default new CommentRepository(); \ No newline at end of file diff --git a/mission 10/src/repositories/likeRepository.ts b/mission 10/src/repositories/likeRepository.ts new file mode 100644 index 000000000..37eb13fbf --- /dev/null +++ b/mission 10/src/repositories/likeRepository.ts @@ -0,0 +1,85 @@ +import prisma from "../lib/prisma"; + +export class LikeRepository { + async findArticle(articleId: number) { + return prisma.article.findUnique({ where: { id: articleId } }); + } + + async findProduct(productId: number) { + return prisma.product.findUnique({ where: { id: productId } }); + } + + async findArticleLike(userId: number, articleId: number) { + return prisma.like.findUnique({ + where: { userId_articleId: { userId, articleId } }, + }); + } + + async findProductLike(userId: number, productId: number) { + return prisma.like.findUnique({ + where: { userId_productId: { userId, productId } }, + }); + } + + async toggleArticleLike(userId: number, articleId: number, current: boolean) { + return prisma.like.update({ + where: { userId_articleId: { userId, articleId } }, + data: { like: !current }, + }); + } + + async toggleProductLike(userId: number, productId: number, current: boolean) { + return prisma.like.update({ + where: { userId_productId: { userId, productId } }, + data: { like: !current }, + }); + } + + async createArticleLike(userId: number, articleId: number) { + return prisma.like.create({ + data: { like: true, userId, articleId }, + }); + } + + async createProductLike(userId: number, productId: number) { + return prisma.like.create({ + data: { like: true, userId, productId }, + }); + } + + async findLikedArticles(userId: number) { + return prisma.like.findMany({ + where: { userId, articleId: { not: null }, like: true }, + include: { + article: { select: { id: true, title: true } }, + }, + }); + } + + async findLikedProducts(userId: number) { + return prisma.like.findMany({ + where: { userId, productId: { not: null }, like: true }, + include: { + product: { select: { id: true, name: true, price: true, tags: true } }, + }, + }); + } + + async findUsersWhoLikedProduct(productId: number) { + const likes = await prisma.like.findMany({ + where: { + productId, + like: true, + }, + select: { + user: { + select: { + id: true, + nickname: true, + }, + }, + }, + }); + return likes.map((like) => like.user); + } +} diff --git a/mission 10/src/repositories/productRepository.ts b/mission 10/src/repositories/productRepository.ts new file mode 100644 index 000000000..62b287709 --- /dev/null +++ b/mission 10/src/repositories/productRepository.ts @@ -0,0 +1,49 @@ +import prisma from "../lib/prisma"; +import { Prisma } from "@prisma/client"; +import { ProductCreateDTO, ProductUpdateDTO, ProductQueryDTO } from "../dtos/product.dto"; + +export class ProductRepository { + async createProduct(data: { userId: number; name: string; description: string; price: number; tags: string }) { + return prisma.product.create({ data }); + } + + async findMany(where: Prisma.ProductWhereInput, skip: number, take: number) { + return prisma.product.findMany({ + skip, + take, + orderBy: { createdAt: "desc" }, + select: { + id: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + where, + }); + } + + async findById(id: number) { + return prisma.product.findUnique({ + where: { id }, + select: { + id: true, + userId: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + }); + } + + async updateProduct(id: number, data: Partial<{ name: string; description: string; price: number; tags: string }>) { + return prisma.product.update({ where: { id }, data }); + } + + async deleteProduct(id: number) { + return prisma.product.delete({ where: { id } }); + } +} \ No newline at end of file diff --git a/mission 10/src/repositories/userRepository.ts b/mission 10/src/repositories/userRepository.ts new file mode 100644 index 000000000..e2eb38b76 --- /dev/null +++ b/mission 10/src/repositories/userRepository.ts @@ -0,0 +1,29 @@ +import prisma from "../lib/prisma"; + +export class UserRepository { + async findByEmail(email: string) { + return prisma.user.findUnique({ where: { email } }); + } + + async findById(id: number) { + return prisma.user.findUnique({ + where: { id }, + select: { id: true, email: true, nickname: true, image: true, createdAt: true, updatedAt: true }, + }); + } + + async createUser(email: string, nickname: string, password: string) { + return prisma.user.create({ data: { email, nickname, password } }); + } + + async updateUser(id: number, data: Partial<{ nickname: string; image: string; password: string }>) { + return prisma.user.update({ where: { id }, data }); + } + + async findProductsByUserId(userId: number) { + return prisma.product.findMany({ + where: { userId }, + select: { name: true, description: true, price: true, tags: true }, + }); + } +} \ No newline at end of file diff --git a/mission 10/src/routers/alertRouter.ts b/mission 10/src/routers/alertRouter.ts new file mode 100644 index 000000000..bfca71a29 --- /dev/null +++ b/mission 10/src/routers/alertRouter.ts @@ -0,0 +1,12 @@ +import express from "express"; +import passport from "../lib/passport"; +import { AlertController } from "../controllers/alertController"; + +const router = express.Router(); +const controller = new AlertController(); + +router.get("/", passport.authenticate("access-token", { session: false }), controller.list); + +router.patch("/:id/read", passport.authenticate("access-token", { session: false }), controller.markAsRead); + +export default router; diff --git a/mission 10/src/routers/articleRouter.ts b/mission 10/src/routers/articleRouter.ts new file mode 100644 index 000000000..d61bb9072 --- /dev/null +++ b/mission 10/src/routers/articleRouter.ts @@ -0,0 +1,15 @@ +import express from "express"; +import passport from "../lib/passport"; +import { ArticleController } from "../controllers/articleController"; + +const router = express.Router(); +const controller = new ArticleController(); + +router.post("/", passport.authenticate("access-token", { session: false }), controller.create); +router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update); +router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete); + +router.get("/", controller.list); +router.get("/:id", controller.detail); + +export default router; diff --git a/mission 10/src/routers/commentRouter.ts b/mission 10/src/routers/commentRouter.ts new file mode 100644 index 000000000..ebc1b38f2 --- /dev/null +++ b/mission 10/src/routers/commentRouter.ts @@ -0,0 +1,16 @@ +import express from "express"; +import passport from "../lib/passport"; +import { CommentController } from "../controllers/commentController"; + +const router = express.Router(); +const controller = new CommentController(); + +router.post("/products/:id", passport.authenticate("access-token", { session: false }), controller.createProductComment); +router.post("/articles/:id", passport.authenticate("access-token", { session: false }), controller.createArticleComment); +router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.modifyComment); +router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.deleteComment); + +router.get("/products/:id", controller.productCommentList); +router.get("/articles/:id", controller.articleCommentList); + +export default router; diff --git a/mission 10/src/routers/index.ts b/mission 10/src/routers/index.ts new file mode 100644 index 000000000..3ecb392d1 --- /dev/null +++ b/mission 10/src/routers/index.ts @@ -0,0 +1,21 @@ +import express from "express"; + +import userRouter from "./userRouter"; +import articleRouter from "./articleRouter"; +import productRouter from "./productRouter"; +import commentRouter from "./commentRouter"; +import likeRouter from "./likeRouter"; +import photoRouter from "./photoRouter"; +import alertRouter from "./alertRouter"; + +const router = express.Router(); + +router.use("/users", userRouter); +router.use("/articles", articleRouter); +router.use("/products", productRouter); +router.use("/comments", commentRouter); +router.use("/likes", likeRouter); +router.use(photoRouter); +router.use("/alerts", alertRouter); + +export default router; \ No newline at end of file diff --git a/mission 10/src/routers/likeRouter.ts b/mission 10/src/routers/likeRouter.ts new file mode 100644 index 000000000..10ec9924d --- /dev/null +++ b/mission 10/src/routers/likeRouter.ts @@ -0,0 +1,13 @@ +import express from "express"; +import passport from "../lib/passport"; +import { LikeController } from "../controllers/likeController"; + +const router = express.Router(); +const controller = new LikeController(); + +router.post("/articles/:id", passport.authenticate("access-token", { session: false }), controller.likeArticle); +router.post("/products/:id", passport.authenticate("access-token", { session: false }), controller.likeProduct); +router.get("/articles", passport.authenticate("access-token", { session: false }), controller.getLikedArticles); +router.get("/products", passport.authenticate("access-token", { session: false }), controller.getLikedProducts); + +export default router; \ No newline at end of file diff --git a/mission 10/src/routers/photoRouter.ts b/mission 10/src/routers/photoRouter.ts new file mode 100644 index 000000000..10e9e9aba --- /dev/null +++ b/mission 10/src/routers/photoRouter.ts @@ -0,0 +1,16 @@ +import express from "express"; +import passport from "../lib/passport"; +import { PhotoController } from "../controllers/photoController"; +import { uploadS3 } from "../lib/s3" + +const router = express.Router(); +const controller = new PhotoController(); + +router.post( + "/", + passport.authenticate("access-token", { session: false }), + uploadS3.single("image"), + controller.upload +); + +export default router; diff --git a/mission 10/src/routers/productRouter.ts b/mission 10/src/routers/productRouter.ts new file mode 100644 index 000000000..5b4e02623 --- /dev/null +++ b/mission 10/src/routers/productRouter.ts @@ -0,0 +1,17 @@ +import express from "express"; +import passport from "../lib/passport"; +import { ProductController } from "../controllers/productController"; + +const router = express.Router(); +const controller = new ProductController(); + +// ✅ 인증 필요 +router.post("/", passport.authenticate("access-token", { session: false }), controller.create); +router.patch("/:id", passport.authenticate("access-token", { session: false }), controller.update); +router.delete("/:id", passport.authenticate("access-token", { session: false }), controller.delete); + +// ✅ 인증 필요 X (공개) +router.get("/", controller.list); +router.get("/:id", controller.detail); + +export default router; diff --git a/mission 10/src/routers/userRouter.ts b/mission 10/src/routers/userRouter.ts new file mode 100644 index 000000000..bdd1f3324 --- /dev/null +++ b/mission 10/src/routers/userRouter.ts @@ -0,0 +1,63 @@ +import express from "express"; +import passport from "../lib/passport"; +import { UserController } from "../controllers/userController"; + +const router = express.Router(); +const controller = new UserController(); + +router.post("/register", controller.register); +router.post( + "/login", + (req, res, next) => { + passport.authenticate( + "local", + { session: false }, + ( + err: any, + user: Express.User | false, + info: { message?: string } | undefined + ) => { + if (err) return next(err); + + if (!user) { + return res.status(401).json({ + message: "Unauthorized", + }); + } + + req.user = user; + next(); + } + )(req, res, next); + }, + controller.login +); + +router.get( + "/profile", + passport.authenticate("access-token", { session: false }), + controller.profile +); +router.patch( + "/modifyInformation", + passport.authenticate("access-token", { session: false }), + controller.modifyInformation +); +router.patch( + "/modifyPassword", + passport.authenticate("access-token", { session: false }), + controller.modifyPassword +); +router.get( + "/products", + passport.authenticate("access-token", { session: false }), + controller.products +); +router.post( + "/refresh", + passport.authenticate("refresh-token", { session: false }), + controller.refreshTokens +); +router.post("/logout", controller.logout); + +export default router; diff --git a/mission 10/src/server.ts b/mission 10/src/server.ts new file mode 100644 index 000000000..9ab83199f --- /dev/null +++ b/mission 10/src/server.ts @@ -0,0 +1,6 @@ +import { app, server } from "./app"; +import { PORT } from "./lib/constants"; + +server.listen(PORT, () => { + console.log(`Server is running on http://localhost:${PORT}`); +}); \ No newline at end of file diff --git a/mission 10/src/services/alertService.ts b/mission 10/src/services/alertService.ts new file mode 100644 index 000000000..e604bb94a --- /dev/null +++ b/mission 10/src/services/alertService.ts @@ -0,0 +1,37 @@ +import { AlertRepository } from "../repositories/alertRepository"; +import { getIo } from "../socket/io"; + +export class AlertService { + private repo = new AlertRepository(); + + async create(userId: number, message: string, link?: string) { + const alert = await this.repo.createAlert({ userId, message, link }); + + const io = getIo(); + io.to(`user:${userId}`).emit("newAlert", alert); + + return alert; + } + + async list(userId: number) { + return this.repo.findByUserId(userId); + } + + async read(alertId: number, userId: number) { + const alert = await this.repo.findById(alertId); + + if (!alert) return false; + + if (alert.userId !== userId) { + return false; + } + + await this.repo.markAsRead(alertId); + + return true; + } + + async countUnread(userId: number) { + return this.repo.countUnread(userId); + } +} diff --git a/mission 10/src/services/articleService.ts b/mission 10/src/services/articleService.ts new file mode 100644 index 000000000..885446aa9 --- /dev/null +++ b/mission 10/src/services/articleService.ts @@ -0,0 +1,46 @@ +import { ArticleRepository } from "../repositories/articleRepository"; +import type { ArticleCreateDTO, ArticleUpdateDTO, ArticleQueryDTO } from "../dtos/article.dto"; +import type { Prisma } from "@prisma/client"; + +export class ArticleService { + private repo = new ArticleRepository(); + + async create(userId: number, data: ArticleCreateDTO) { + return this.repo.createArticle({ ...data, userId }); + } + + async list({ page, pageSize, keyword }: ArticleQueryDTO) { + const where: Prisma.ArticleWhereInput = keyword + ? { + OR: [ + { title: { contains: keyword, mode: "insensitive" } }, + { content: { contains: keyword, mode: "insensitive" } }, + ], + } + : {}; + + return this.repo.findMany(where, (page - 1) * pageSize, pageSize); + } + + async getDetail(id: number) { + return this.repo.findById(id); + } + + async update(userId: number, data: ArticleUpdateDTO, articleId: number) { + const article = await this.repo.findById(articleId); + if (!article) throw new Error("NOT_FOUND"); + if (article.userId !== userId) throw new Error("FORBIDDEN"); + + return this.repo.updatedArticle(articleId, data); + } + + async delete(userId: number, articleId: number) { + const article = await this.repo.findById(articleId); + if (!article) throw new Error("NOT_FOUND"); + if (article.userId !== userId) throw new Error("FORBIDDEN"); + + await this.repo.deleteArticle(articleId); + } +} + +export default new ArticleService(); \ No newline at end of file diff --git a/mission 10/src/services/commentService.ts b/mission 10/src/services/commentService.ts new file mode 100644 index 000000000..eec34093f --- /dev/null +++ b/mission 10/src/services/commentService.ts @@ -0,0 +1,87 @@ +import { CommentRepository } from "../repositories/commentRepository"; +import { ArticleRepository } from "../repositories/articleRepository"; +import { ProductRepository } from "../repositories/productRepository"; +import { AlertService } from "../services/alertService"; + +export class CommentService { + private repo = new CommentRepository(); + private articleRepo = new ArticleRepository(); + private productRepo = new ProductRepository(); + private alertService = new AlertService(); + + async createArticleComment( + userId: number, + articleId: number, + content: string + ) { + const article = await this.articleRepo.findById(articleId); + if (!article) { + throw new Error("Article not found"); + } + + const comment = await this.repo.createArticleComment( + userId, + articleId, + content + ); + + if (article && article.userId !== userId) { + await this.alertService.create( + article.userId, + "내 게시글에 새로운 댓글이 달렸습니다.", + `/articles/${articleId}` + ); + } + + return comment; + } + + async createProductComment( + userId: number, + productId: number, + content: string + ) { + const product = await this.productRepo.findById(productId); + if (!product) { + throw new Error("Product not found"); + } + + const comment = await this.repo.createProductComment( + userId, + productId, + content + ); + + if (product && product.userId !== userId) { + await this.alertService.create( + product.userId, + "내 판매글에 새로운 댓글이 달렸습니다.", + `/products/${productId}` + ); + } + + return comment; + } + + async updateComment(userId: number, commentId: number, content: string) { + const comment = await this.repo.findById(commentId); + if (!comment) throw new Error("NOT_FOUND"); + if (comment.userId !== userId) throw new Error("FORBIDDEN"); + return this.repo.updateComment(commentId, content); + } + + async deleteComment(userId: number, commentId: number) { + const comment = await this.repo.findById(commentId); + if (!comment) throw new Error("NOT_FOUND"); + if (comment.userId !== userId) throw new Error("FORBIDDEN"); + await this.repo.deleteComment(commentId); + } + + async getProductComments(productId: number, lastId?: number) { + return this.repo.findProductComments(productId, lastId); + } + + async getArticleComments(articleId: number, lastId?: number) { + return this.repo.findArticleComments(articleId, lastId); + } +} diff --git a/mission 10/src/services/likeService.ts b/mission 10/src/services/likeService.ts new file mode 100644 index 000000000..4f7118e7f --- /dev/null +++ b/mission 10/src/services/likeService.ts @@ -0,0 +1,35 @@ +import { LikeRepository } from "../repositories/likeRepository"; + +export class LikeService { + private repo = new LikeRepository(); + + async likeArticle(userId: number, articleId: number) { + const article = await this.repo.findArticle(articleId); + if (!article) throw new Error("ARTICLE_NOT_FOUND"); + + const existing = await this.repo.findArticleLike(userId, articleId); + if (existing) { + return this.repo.toggleArticleLike(userId, articleId, existing.like); + } + return this.repo.createArticleLike(userId, articleId); + } + + async likeProduct(userId: number, productId: number) { + const product = await this.repo.findProduct(productId); + if (!product) throw new Error("PRODUCT_NOT_FOUND"); + + const existing = await this.repo.findProductLike(userId, productId); + if (existing) { + return this.repo.toggleProductLike(userId, productId, existing.like); + } + return this.repo.createProductLike(userId, productId); + } + + async getLikedArticles(userId: number) { + return this.repo.findLikedArticles(userId); + } + + async getLikedProducts(userId: number) { + return this.repo.findLikedProducts(userId); + } +} \ No newline at end of file diff --git a/mission 10/src/services/productService.ts b/mission 10/src/services/productService.ts new file mode 100644 index 000000000..d4b931371 --- /dev/null +++ b/mission 10/src/services/productService.ts @@ -0,0 +1,68 @@ +import { ProductRepository } from "../repositories/productRepository"; +import { LikeRepository } from "../repositories/likeRepository"; +import { AlertService } from "../services/alertService"; +import type { ProductCreateDTO, ProductQueryDTO } from "../dtos/product.dto"; +import type { Prisma } from "@prisma/client"; + +export class ProductService { + private repo = new ProductRepository(); + private likeRepo = new LikeRepository(); + private alertService = new AlertService(); + + async create(userId: number, data: ProductCreateDTO) { + return this.repo.createProduct({ ...data, userId }); + } + + async list({ page, pageSize, keyword }: ProductQueryDTO) { + const where: Prisma.ProductWhereInput = keyword + ? { + OR: [ + { name: { contains: keyword, mode: "insensitive" } }, + { description: { contains: keyword, mode: "insensitive" } }, + ], + } + : {}; + return this.repo.findMany(where, (page - 1) * pageSize, pageSize); + } + + async getDetail(id: number) { + return this.repo.findById(id); + } + + async update( + userId: number, + productId: number, + data: { name?: string; description?: string; price?: number; tags?: string } + ) { + const product = await this.repo.findById(productId); + if (!product) throw new Error("NOT_FOUND"); + if (product.userId !== userId) throw new Error("FORBIDDEN"); + + const oldPrice = product.price; + const updated = await this.repo.updateProduct(productId, data); + + if (data.price !== undefined && data.price !== oldPrice) { + const likedUsers = await this.likeRepo.findUsersWhoLikedProduct(productId); + + const targetUsers = likedUsers.filter((u) => u.id !== userId); + + for (const user of targetUsers) { + await this.alertService.create( + user.id, + `좋아요한 상품 "${updated.name}"의 가격이 ${oldPrice}원 → ${data.price}원으로 변경되었습니다.`, + `/products/${productId}` + ); + } + } + + return updated; + } + + async delete(userId: number, productId: number) { + const product = await this.repo.findById(productId); + if (!product) throw new Error("NOT_FOUND"); + if (product.userId !== userId) throw new Error("FORBIDDEN"); + + await this.repo.deleteProduct(productId); + } +} diff --git a/mission 10/src/services/userService.ts b/mission 10/src/services/userService.ts new file mode 100644 index 000000000..f9bd91fc2 --- /dev/null +++ b/mission 10/src/services/userService.ts @@ -0,0 +1,48 @@ +import bcrypt from "bcrypt"; +import { UserRepository } from "../repositories/userRepository"; +import { generateTokens } from "../lib/token"; +import type { UserRegisterDTO, UserUpdateDTO, UserPasswordDTO } from "../dtos/user.dto"; + +export class UserService { + private userRepo = new UserRepository(); + + async register(data: UserRegisterDTO) { + const exists = await this.userRepo.findByEmail(data.email); + if (exists) throw new Error("EMAIL_EXISTS"); + + const salt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(data.password, salt); + + await this.userRepo.createUser(data.email, data.nickname, hashedPassword); + return { message: "User registered successfully" }; + } + + async getProfile(userId: number) { + return this.userRepo.findById(userId); + } + + async updateInformation(userId: number, nickname?: string, image?: string) { + const updateData: Record = {}; + if (nickname) updateData.nickname = nickname; + if (image) updateData.image = image; + + if (Object.keys(updateData).length === 0) throw new Error("NO_DATA"); + + return this.userRepo.updateUser(userId, updateData); + } + + async updatePassword(userId: number, data: UserPasswordDTO) { + const salt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(data.password, salt); + await this.userRepo.updateUser(userId, { password: hashedPassword }); + return { message: "Password updated successfully" }; + } + + async getProducts(userId: number) { + return this.userRepo.findProductsByUserId(userId); + } + + generateUserTokens(userId: number) { + return generateTokens(userId); + } +} diff --git a/mission 10/src/socket/io.ts b/mission 10/src/socket/io.ts new file mode 100644 index 000000000..4af5cf407 --- /dev/null +++ b/mission 10/src/socket/io.ts @@ -0,0 +1,20 @@ +import { Server } from "socket.io"; + +let io: Server | null = null; + +export function initIo(server: any) { + io = new Server(server, { + cors: { + origin: "http://localhost:3000", + methods: ["GET", "POST"], + }, + }); + return io; +} + +export function getIo(): Server { + if (!io) { + throw new Error("Socket.io has not been initialized!"); + } + return io; +} diff --git a/mission 10/src/socket/socket.ts b/mission 10/src/socket/socket.ts new file mode 100644 index 000000000..bab36f577 --- /dev/null +++ b/mission 10/src/socket/socket.ts @@ -0,0 +1,23 @@ +import { getIo } from "./io"; +import jwt from "jsonwebtoken"; + +export function registerSocket() { + const io = getIo(); + + io.on("connection", (socket) => { + console.log("Socket connected:", socket.id); + + const token = socket.handshake.auth?.token; + if (!token) return socket.disconnect(); + + try { + const decoded = jwt.verify(token, process.env.JWT_SECRET!) as { + id: number; + }; + + socket.join(`user:${decoded.id}`); + } catch (err) { + socket.disconnect(); + } + }); +} diff --git a/mission 10/src/types/express.d.ts b/mission 10/src/types/express.d.ts new file mode 100644 index 000000000..f30ba2233 --- /dev/null +++ b/mission 10/src/types/express.d.ts @@ -0,0 +1,9 @@ +import type { User as PrismaUser } from "@prisma/client"; + +declare global { + namespace Express { + interface User extends PrismaUser {} + } +} + +export {}; \ No newline at end of file diff --git a/mission 10/test.http b/mission 10/test.http new file mode 100644 index 000000000..cc1f46c72 --- /dev/null +++ b/mission 10/test.http @@ -0,0 +1,36 @@ +curl -X POST \ + -H "Content-Type: application/json" \ + -d '{"email": "test@example.com", "nickname": "test", "password": "password123"}' \ + http://localhost:3000/users/register + +### + curl -X POST \ + -H "Content-Type: application/json" \ + -d '{"email": "test@example.com", "password": "password123"}' \ + "http://localhost:3000/users/login" + +### + curl -X POST \ +-H "Content-Type: application/json" \ +-b "access-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsImlhdCI6MTc2MjIzMzM2MSwiZXhwIjoxNzYyMjM2OTYxfQ.NND1H5Wao2Gq_yYZz31bLtzEw9AaEGNMgD8RE-8bGKU" \ +-d '{ "title": "테스트", "content": "테스트테스트테스트테스트"}' \ +"http://localhost:3000/articles" + +### + curl -X POST \ +-H "Content-Type: application/json" \ +-b "access-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsImlhdCI6MTc2MjIzMzM2MSwiZXhwIjoxNzYyMjM2OTYxfQ.NND1H5Wao2Gq_yYZz31bLtzEw9AaEGNMgD8RE-8bGKU" \ +-d '{ "content": "덧글 테스트"}' \ +"http://localhost:3000/comments/articles/1" + +### + curl -X GET \ +-H "Content-Type: application/json" \ +-b "access-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsImlhdCI6MTc2MjI0MzQ0MiwiZXhwIjoxNzYyMjQ3MDQyfQ.kGHITSzklAyDEVQWxMZlIlUdwrcy76-UB-t_qXLySto" \ +"http://localhost:3000/comments/articles/1" + +### + curl -X GET \ +-H "Content-Type: application/json" \ +-b "access-token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsImlhdCI6MTc2MjI0MzQ0MiwiZXhwIjoxNzYyMjQ3MDQyfQ.kGHITSzklAyDEVQWxMZlIlUdwrcy76-UB-t_qXLySto" \ +"http://localhost:3000/alerts/1" \ No newline at end of file diff --git a/mission 10/tests/article.integration.test.ts b/mission 10/tests/article.integration.test.ts new file mode 100644 index 000000000..268994f46 --- /dev/null +++ b/mission 10/tests/article.integration.test.ts @@ -0,0 +1,70 @@ +import request from "supertest"; +import { app, server } from "../src/app"; +import { loginAndGetToken } from "./helpers/auth"; +import { ArticleRepository } from "../src/repositories/articleRepository"; + +describe("Article API Integration Test", () => { + let accessToken: string; + let articleId: number; + let userId: number; + + beforeAll(async () => { + const tokens = await loginAndGetToken(); + accessToken = tokens.accessToken; + userId = tokens.userId; + + + if (!server.listening) { + await new Promise((resolve) => server.listen(0, resolve)); + } + + const articleRepo = new ArticleRepository(); + const article = await articleRepo.createArticle({ + userId, + title: "테스트 게시글", + content: "테스트용 내용", + }); + articleId = article.id; + }); + + afterAll(async () => { + await new Promise((resolve, reject) => { + server.close((err) => (err ? reject(err) : resolve())); + }); + }); + + describe("Public Article API", () => { + it("게시글 목록 조회", async () => { + const res = await request(app).get("/articles").expect(200); + expect(Array.isArray(res.body)).toBe(true); + }); + + it("게시글 상세 조회", async () => { + const res = await request(app).get(`/articles/${articleId}`).expect(200); + + expect(res.body).toHaveProperty("id", articleId); + expect(res.body).toHaveProperty("title", "테스트 게시글"); + }); + }); + + describe("Private Article API", () => { + it("게시글 수정", async () => { + const res = await request(app) + .patch(`/articles/${articleId}`) + .set("Authorization", `Bearer ${accessToken}`) + .send({ title: "수정된 제목" }) + .expect(200); + + expect(res.body).toHaveProperty("title", "수정된 제목"); + }); + + it("게시글 삭제", async () => { + await request(app) + .delete(`/articles/${articleId}`) + .set("Authorization", `Bearer ${accessToken}`) + .expect(204); + + await request(app).get(`/articles/${articleId}`).expect(404); + }); + }); +}); diff --git a/mission 10/tests/helpers/auth.ts b/mission 10/tests/helpers/auth.ts new file mode 100644 index 000000000..3bc8e9074 --- /dev/null +++ b/mission 10/tests/helpers/auth.ts @@ -0,0 +1,39 @@ +import request from "supertest"; +import { app } from "../../src/app"; +import bcrypt from "bcrypt"; +import { UserRepository } from "../../src/repositories/userRepository"; + +interface TokenResponse { + accessToken: string; + refreshToken?: string; +} + +export async function loginAndGetToken( + email?: string, + password = "123456" +): Promise<{ accessToken: string; refreshToken?: string; userId: number }> { + const userRepo = new UserRepository(); + + email = email ?? `test${Date.now()}@test.com`; + + let existing = await userRepo.findByEmail(email); + + if (!existing) { + const hashed = await bcrypt.hash(password, 10); + existing = await userRepo.createUser(email, "tester", hashed); + } + + const res = await request(app) + .post("/users/login") + .send({ email, password }) + .expect(200); + + console.log("Login response body:", res.body); + + const { accessToken, refreshToken } = res.body; + if (!accessToken) { + throw new Error("로그인 실패: accessToken이 반환되지 않았습니다."); + } + + return { accessToken, refreshToken, userId: existing.id }; +} diff --git a/mission 10/tests/helpers/db.ts b/mission 10/tests/helpers/db.ts new file mode 100644 index 000000000..2c5b96d5b --- /dev/null +++ b/mission 10/tests/helpers/db.ts @@ -0,0 +1,9 @@ +import { PrismaClient } from "@prisma/client"; + +const prisma = new PrismaClient(); + +export async function clearDatabase() { + await prisma.article.deleteMany(); + await prisma.product.deleteMany(); + await prisma.user.deleteMany(); +} diff --git a/mission 10/tests/product.integration.test.ts b/mission 10/tests/product.integration.test.ts new file mode 100644 index 000000000..cfe6d017f --- /dev/null +++ b/mission 10/tests/product.integration.test.ts @@ -0,0 +1,73 @@ +import request from "supertest"; +import { app, server } from "../src/app"; +import { loginAndGetToken } from "./helpers/auth"; +import { ProductRepository } from "../src/repositories/productRepository"; + +describe("Product API Integration Test", () => { + let accessToken: string; + let userId: number; + let productId: number; + + beforeAll(async () => { + const tokens = await loginAndGetToken(); + accessToken = tokens.accessToken; + userId = tokens.userId; + + if (!server.listening) { + await new Promise((resolve) => server.listen(0, resolve)); + } + + const productRepo = new ProductRepository(); + const product = await productRepo.createProduct({ + userId, + name: "상품", + description: "설명", + price: 1000, + tags: "상품", + }); + productId = product.id; + }); + + afterAll(async () => { + await new Promise((resolve, reject) => { + server.close((err) => (err ? reject(err) : resolve())); + }); + }); + + describe("Public Product API", () => { + it("상품 목록 조회", async () => { + const res = await request(app).get("/products").expect(200); + expect(Array.isArray(res.body)).toBe(true); + }); + + it("상품 상세 조회", async () => { + const res = await request(app) + .get(`/products/${productId}`) + .expect(200); + + expect(res.body).toHaveProperty("id", productId); + expect(res.body).toHaveProperty("name", "상품"); + }); + }); + + describe("Private Product API", () => { + it("상품 수정", async () => { + const res = await request(app) + .patch(`/products/${productId}`) + .set("Authorization", `Bearer ${accessToken}`) + .send({ price: 2000 }) + .expect(200); + + expect(res.body).toHaveProperty("price", 2000); + }); + + it("상품 삭제", async () => { + await request(app) + .delete(`/products/${productId}`) + .set("Authorization", `Bearer ${accessToken}`) + .expect(204); + + await request(app).get(`/products/${productId}`).expect(404); + }); + }); +}); diff --git a/mission 10/tests/user.integration.test.ts b/mission 10/tests/user.integration.test.ts new file mode 100644 index 000000000..c2b9a2757 --- /dev/null +++ b/mission 10/tests/user.integration.test.ts @@ -0,0 +1,76 @@ +import request from "supertest"; +import { app, server } from "../src/app"; +import { clearDatabase } from "./helpers/db"; +import { UserRepository } from "../src/repositories/userRepository"; +import bcrypt from "bcrypt"; + +describe("User API Integration Test", () => { + let accessToken: string; + let testEmail: string; + let testPassword = "123456"; + let userId: number; + + beforeAll(async () => { + await clearDatabase(); + + if (!server.listening) { + await new Promise((resolve) => server.listen(0, resolve)); + } + + testEmail = `user_${Date.now()}@test.com`; + + const userRepo = new UserRepository(); + const hashed = await bcrypt.hash(testPassword, 10); + + const user = await userRepo.createUser(testEmail, "tester", hashed); + userId = user.id; + }); + + afterAll(async () => { + await new Promise((resolve, reject) => { + server.close((err) => (err ? reject(err) : resolve())); + }); + }); + + describe("User Login", () => { + it("로그인 성공", async () => { + const res = await request(app) + .post("/users/login") + .send({ email: testEmail, password: testPassword }) + .expect(200); + + expect(res.body).toHaveProperty("accessToken"); + expect(res.body).toHaveProperty("refreshToken"); + accessToken = res.body.accessToken; + }); + + it("잘못된 비밀번호 로그인 실패", async () => { + const res = await request(app) + .post("/users/login") + .send({ email: testEmail, password: "wrong" }) + .expect(401); + + expect(res.body).toHaveProperty("message"); + expect(res.body.message).toBe("Unauthorized"); + }); + }); + + describe("User Registration", () => { + it("회원가입 성공", async () => { + const newEmail = `reg_${Date.now()}@test.com`; + const res = await request(app) + .post("/users/register") + .send({ email: newEmail, password: "123456", nickname: "tester" }) + .expect(201); + + expect(res.body).toHaveProperty("message"); + }); + + it("중복 이메일 회원가입 실패", async () => { + await request(app) + .post("/users/register") + .send({ email: testEmail, password: "123456", nickname: "dup" }) + .expect(409); + }); + }); +}); diff --git a/mission 10/tsconfig.json b/mission 10/tsconfig.json new file mode 100644 index 000000000..f052e7e3b --- /dev/null +++ b/mission 10/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + /* ----- 기본 옵션 ----- */ + "target": "ES2020", // 어떤 버전의 JavaScript로 컴파일할지 (ES2020은 최신 Node.js와 호환성이 좋음) + "module": "commonjs", // Node.js 환경에서 사용하는 모듈 시스템 + "rootDir": "./src", // 타입스크립트 소스코드의 루트 폴더 + "outDir": "./dist", // 컴파일된 JavaScript 파일이 저장될 폴더 + + /* ----- 엄격한 타입 검사 옵션 (강력 추천) ----- */ + "strict": true, // 모든 엄격한 타입 검사 옵션을 활성화 (가장 중요!) + "noImplicitAny": true, // 'any' 타입을 명시적으로 사용하지 않으면 에러 발생 + + /* ----- 모듈 관련 옵션 ----- */ + "moduleResolution": "node", // 모듈 해석 방식을 Node.js 스타일로 설정 + "esModuleInterop": true, // CommonJS 모듈을 ES 모듈 방식으로 'import' 할 수 있게 해줌 (예: import express from 'express') + "resolveJsonModule": true, // .json 파일을 모듈처럼 import 할 수 있게 허용 + + /* ----- 추가 옵션 ----- */ + "sourceMap": true, // .map 파일을 생성하여, 디버깅 시 ts 코드를 볼 수 있게 함 + "forceConsistentCasingInFileNames": true, // 파일 이름의 대소문자를 구분하도록 강제 + "skipLibCheck": true, // 의존하는 라이브러리(*.d.ts)의 타입 검사를 건너뛰어 컴파일 속도 향상 + "typeRoots": ["./node_modules/@types", "./src/types"] + }, + "include": ["src/**/*"], // 컴파일할 파일 범위 (src 폴더 아래의 모든 파일) + "exclude": ["node_modules", "dist"], // 컴파일에서 제외할 폴더 + "ts-node": { + "files": true + } +} From 76e4fd9b217117d9f1a989af91f760a5abf14a65 Mon Sep 17 00:00:00 2001 From: Batur-s Date: Tue, 18 Nov 2025 17:04:52 +0900 Subject: [PATCH 36/38] [fix] change acl --- mission 10/package.json | 2 +- mission 10/src/lib/s3.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/mission 10/package.json b/mission 10/package.json index 53cfc0bac..93551d7a7 100644 --- a/mission 10/package.json +++ b/mission 10/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "main": "index.js", "scripts": { - "dev": "ts-node --files src/app.ts", + "dev": "ts-node --files src/server.ts", "start": "node dist/app.js", "lint": "eslint . --ext .ts", "prisma:generate": "prisma generate", diff --git a/mission 10/src/lib/s3.ts b/mission 10/src/lib/s3.ts index db307acd2..4a934c82a 100644 --- a/mission 10/src/lib/s3.ts +++ b/mission 10/src/lib/s3.ts @@ -20,7 +20,6 @@ export const uploadS3 = multer({ }, region: process.env.AWS_REGION, }), - acl: "public-read-write", bucket: process.env.AWS_S3_BUCKET!, contentType: multerS3.AUTO_CONTENT_TYPE, key: (req, file, cb) => { From bf750d637a6fbbb06b908ca3523a0a540868ea35 Mon Sep 17 00:00:00 2001 From: Batur-s Date: Tue, 25 Nov 2025 09:02:50 +0900 Subject: [PATCH 37/38] [fix] fixed config --- mission 10/dist/app.js | 35 + mission 10/dist/app.js.map | 1 + .../dist/controllers/alertController.js | 38 + .../dist/controllers/alertController.js.map | 1 + .../dist/controllers/articleController.js | 81 + .../dist/controllers/articleController.js.map | 1 + .../dist/controllers/commentController.js | 100 + .../dist/controllers/commentController.js.map | 1 + mission 10/dist/controllers/likeController.js | 63 + .../dist/controllers/likeController.js.map | 1 + .../dist/controllers/photoController.js | 33 + .../dist/controllers/photoController.js.map | 1 + .../dist/controllers/productController.js | 81 + .../dist/controllers/productController.js.map | 1 + mission 10/dist/controllers/userController.js | 102 + .../dist/controllers/userController.js.map | 1 + mission 10/dist/dtos/article.dto.js | 36 + mission 10/dist/dtos/article.dto.js.map | 1 + mission 10/dist/dtos/product.dto.js | 25 + mission 10/dist/dtos/product.dto.js.map | 1 + mission 10/dist/dtos/user.dto.js | 25 + mission 10/dist/dtos/user.dto.js.map | 1 + mission 10/dist/lib/constants.js | 21 + mission 10/dist/lib/constants.js.map | 1 + mission 10/dist/lib/cookieUtil.js | 23 + mission 10/dist/lib/cookieUtil.js.map | 1 + mission 10/dist/lib/passport/index.js | 13 + mission 10/dist/lib/passport/index.js.map | 1 + mission 10/dist/lib/passport/jwtStrategy.js | 37 + .../dist/lib/passport/jwtStrategy.js.map | 1 + mission 10/dist/lib/passport/localStrategy.js | 29 + .../dist/lib/passport/localStrategy.js.map | 1 + mission 10/dist/lib/prisma.js | 6 + mission 10/dist/lib/prisma.js.map | 1 + mission 10/dist/lib/s3.js | 34 + mission 10/dist/lib/s3.js.map | 1 + mission 10/dist/lib/token.js | 28 + mission 10/dist/lib/token.js.map | 1 + mission 10/dist/middlewares/errorHandler.js | 21 + .../dist/middlewares/errorHandler.js.map | 1 + .../dist/repositories/alertRepository.js | 36 + .../dist/repositories/alertRepository.js.map | 1 + .../dist/repositories/articleRepository.js | 41 + .../repositories/articleRepository.js.map | 1 + .../dist/repositories/commentRepository.js | 52 + .../repositories/commentRepository.js.map | 1 + .../dist/repositories/likeRepository.js | 82 + .../dist/repositories/likeRepository.js.map | 1 + .../dist/repositories/productRepository.js | 50 + .../repositories/productRepository.js.map | 1 + .../dist/repositories/userRepository.js | 32 + .../dist/repositories/userRepository.js.map | 1 + mission 10/dist/routers/alertRouter.js | 14 + mission 10/dist/routers/alertRouter.js.map | 1 + mission 10/dist/routers/articleRouter.js | 17 + mission 10/dist/routers/articleRouter.js.map | 1 + mission 10/dist/routers/commentRouter.js | 18 + mission 10/dist/routers/commentRouter.js.map | 1 + mission 10/dist/routers/index.js | 23 + mission 10/dist/routers/index.js.map | 1 + mission 10/dist/routers/likeRouter.js | 16 + mission 10/dist/routers/likeRouter.js.map | 1 + mission 10/dist/routers/photoRouter.js | 14 + mission 10/dist/routers/photoRouter.js.map | 1 + mission 10/dist/routers/productRouter.js | 19 + mission 10/dist/routers/productRouter.js.map | 1 + mission 10/dist/routers/userRouter.js | 32 + mission 10/dist/routers/userRouter.js.map | 1 + mission 10/dist/server.js | 8 + mission 10/dist/server.js.map | 1 + mission 10/dist/services/alertService.js | 34 + mission 10/dist/services/alertService.js.map | 1 + mission 10/dist/services/articleService.js | 45 + .../dist/services/articleService.js.map | 1 + mission 10/dist/services/commentService.js | 61 + .../dist/services/commentService.js.map | 1 + mission 10/dist/services/likeService.js | 37 + mission 10/dist/services/likeService.js.map | 1 + mission 10/dist/services/productService.js | 57 + .../dist/services/productService.js.map | 1 + mission 10/dist/services/userService.js | 50 + mission 10/dist/services/userService.js.map | 1 + mission 10/dist/socket/io.js | 22 + mission 10/dist/socket/io.js.map | 1 + mission 10/dist/socket/socket.js | 25 + mission 10/dist/socket/socket.js.map | 1 + mission 10/package.json | 5 +- mission 9/package-lock.json | 11856 +++++++++++----- mission 9/package.json | 3 +- 89 files changed, 9786 insertions(+), 3737 deletions(-) create mode 100644 mission 10/dist/app.js create mode 100644 mission 10/dist/app.js.map create mode 100644 mission 10/dist/controllers/alertController.js create mode 100644 mission 10/dist/controllers/alertController.js.map create mode 100644 mission 10/dist/controllers/articleController.js create mode 100644 mission 10/dist/controllers/articleController.js.map create mode 100644 mission 10/dist/controllers/commentController.js create mode 100644 mission 10/dist/controllers/commentController.js.map create mode 100644 mission 10/dist/controllers/likeController.js create mode 100644 mission 10/dist/controllers/likeController.js.map create mode 100644 mission 10/dist/controllers/photoController.js create mode 100644 mission 10/dist/controllers/photoController.js.map create mode 100644 mission 10/dist/controllers/productController.js create mode 100644 mission 10/dist/controllers/productController.js.map create mode 100644 mission 10/dist/controllers/userController.js create mode 100644 mission 10/dist/controllers/userController.js.map create mode 100644 mission 10/dist/dtos/article.dto.js create mode 100644 mission 10/dist/dtos/article.dto.js.map create mode 100644 mission 10/dist/dtos/product.dto.js create mode 100644 mission 10/dist/dtos/product.dto.js.map create mode 100644 mission 10/dist/dtos/user.dto.js create mode 100644 mission 10/dist/dtos/user.dto.js.map create mode 100644 mission 10/dist/lib/constants.js create mode 100644 mission 10/dist/lib/constants.js.map create mode 100644 mission 10/dist/lib/cookieUtil.js create mode 100644 mission 10/dist/lib/cookieUtil.js.map create mode 100644 mission 10/dist/lib/passport/index.js create mode 100644 mission 10/dist/lib/passport/index.js.map create mode 100644 mission 10/dist/lib/passport/jwtStrategy.js create mode 100644 mission 10/dist/lib/passport/jwtStrategy.js.map create mode 100644 mission 10/dist/lib/passport/localStrategy.js create mode 100644 mission 10/dist/lib/passport/localStrategy.js.map create mode 100644 mission 10/dist/lib/prisma.js create mode 100644 mission 10/dist/lib/prisma.js.map create mode 100644 mission 10/dist/lib/s3.js create mode 100644 mission 10/dist/lib/s3.js.map create mode 100644 mission 10/dist/lib/token.js create mode 100644 mission 10/dist/lib/token.js.map create mode 100644 mission 10/dist/middlewares/errorHandler.js create mode 100644 mission 10/dist/middlewares/errorHandler.js.map create mode 100644 mission 10/dist/repositories/alertRepository.js create mode 100644 mission 10/dist/repositories/alertRepository.js.map create mode 100644 mission 10/dist/repositories/articleRepository.js create mode 100644 mission 10/dist/repositories/articleRepository.js.map create mode 100644 mission 10/dist/repositories/commentRepository.js create mode 100644 mission 10/dist/repositories/commentRepository.js.map create mode 100644 mission 10/dist/repositories/likeRepository.js create mode 100644 mission 10/dist/repositories/likeRepository.js.map create mode 100644 mission 10/dist/repositories/productRepository.js create mode 100644 mission 10/dist/repositories/productRepository.js.map create mode 100644 mission 10/dist/repositories/userRepository.js create mode 100644 mission 10/dist/repositories/userRepository.js.map create mode 100644 mission 10/dist/routers/alertRouter.js create mode 100644 mission 10/dist/routers/alertRouter.js.map create mode 100644 mission 10/dist/routers/articleRouter.js create mode 100644 mission 10/dist/routers/articleRouter.js.map create mode 100644 mission 10/dist/routers/commentRouter.js create mode 100644 mission 10/dist/routers/commentRouter.js.map create mode 100644 mission 10/dist/routers/index.js create mode 100644 mission 10/dist/routers/index.js.map create mode 100644 mission 10/dist/routers/likeRouter.js create mode 100644 mission 10/dist/routers/likeRouter.js.map create mode 100644 mission 10/dist/routers/photoRouter.js create mode 100644 mission 10/dist/routers/photoRouter.js.map create mode 100644 mission 10/dist/routers/productRouter.js create mode 100644 mission 10/dist/routers/productRouter.js.map create mode 100644 mission 10/dist/routers/userRouter.js create mode 100644 mission 10/dist/routers/userRouter.js.map create mode 100644 mission 10/dist/server.js create mode 100644 mission 10/dist/server.js.map create mode 100644 mission 10/dist/services/alertService.js create mode 100644 mission 10/dist/services/alertService.js.map create mode 100644 mission 10/dist/services/articleService.js create mode 100644 mission 10/dist/services/articleService.js.map create mode 100644 mission 10/dist/services/commentService.js create mode 100644 mission 10/dist/services/commentService.js.map create mode 100644 mission 10/dist/services/likeService.js create mode 100644 mission 10/dist/services/likeService.js.map create mode 100644 mission 10/dist/services/productService.js create mode 100644 mission 10/dist/services/productService.js.map create mode 100644 mission 10/dist/services/userService.js create mode 100644 mission 10/dist/services/userService.js.map create mode 100644 mission 10/dist/socket/io.js create mode 100644 mission 10/dist/socket/io.js.map create mode 100644 mission 10/dist/socket/socket.js create mode 100644 mission 10/dist/socket/socket.js.map diff --git a/mission 10/dist/app.js b/mission 10/dist/app.js new file mode 100644 index 000000000..a807e8312 --- /dev/null +++ b/mission 10/dist/app.js @@ -0,0 +1,35 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.server = exports.app = void 0; +const express_1 = __importDefault(require("express")); +const cookie_parser_1 = __importDefault(require("cookie-parser")); +const index_1 = __importDefault(require("./routers/index")); +const index_2 = __importDefault(require("./lib/passport/index")); +const cors_1 = __importDefault(require("cors")); +const errorHandler_1 = require("./middlewares/errorHandler"); +const http_1 = __importDefault(require("http")); +const io_1 = require("./socket/io"); // ⬅ io 초기화 함수만 import +const socket_1 = require("./socket/socket"); // ⬅ 소켓 이벤트 등록 +const app = (0, express_1.default)(); +exports.app = app; +app.use(express_1.default.urlencoded({ extended: true })); +app.use(express_1.default.json()); +app.use((0, cookie_parser_1.default)()); +const corsOptions = { + origin: "http://localhost:3000", + optionsSuccessStatus: 200, + credentials: true, +}; +app.use((0, cors_1.default)(corsOptions)); +app.use(index_2.default.initialize()); +app.use(index_1.default); +app.use(errorHandler_1.errorHandler); +const server = http_1.default.createServer(app); +exports.server = server; +(0, io_1.initIo)(server); +(0, socket_1.registerSocket)(); +exports.default = app; +//# sourceMappingURL=app.js.map \ No newline at end of file diff --git a/mission 10/dist/app.js.map b/mission 10/dist/app.js.map new file mode 100644 index 000000000..c3befabf0 --- /dev/null +++ b/mission 10/dist/app.js.map @@ -0,0 +1 @@ +{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":";;;;;;AAAA,sDAA8B;AAC9B,kEAAyC;AACzC,4DAAqC;AACrC,iEAA4C;AAC5C,gDAAwB;AACxB,6DAA0D;AAC1D,gDAAwB;AACxB,oCAAqC,CAAC,sBAAsB;AAC5D,4CAAiD,CAAC,cAAc;AAEhE,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;AA2Bb,kBAAG;AAzBZ,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAChD,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AACxB,GAAG,CAAC,GAAG,CAAC,IAAA,uBAAY,GAAE,CAAC,CAAC;AAExB,MAAM,WAAW,GAAG;IAClB,MAAM,EAAE,uBAAuB;IAC/B,oBAAoB,EAAE,GAAG;IACzB,WAAW,EAAE,IAAI;CAClB,CAAC;AACF,GAAG,CAAC,GAAG,CAAC,IAAA,cAAI,EAAC,WAAW,CAAC,CAAC,CAAC;AAE3B,GAAG,CAAC,GAAG,CAAC,eAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;AAC/B,GAAG,CAAC,GAAG,CAAC,eAAM,CAAC,CAAC;AAEhB,GAAG,CAAC,GAAG,CAAC,2BAAY,CAAC,CAAC;AAEtB,MAAM,MAAM,GAAG,cAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;AASxB,wBAAM;AAPpB,IAAA,WAAM,EAAC,MAAM,CAAC,CAAC;AACf,IAAA,uBAAc,GAAE,CAAC;AAOjB,kBAAe,GAAG,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/controllers/alertController.js b/mission 10/dist/controllers/alertController.js new file mode 100644 index 000000000..680630832 --- /dev/null +++ b/mission 10/dist/controllers/alertController.js @@ -0,0 +1,38 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.AlertController = void 0; +const alertService_1 = require("../services/alertService"); +const http_status_1 = __importDefault(require("http-status")); +class AlertController { + constructor() { + this.service = new alertService_1.AlertService(); + this.list = async (req, res) => { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + const userId = req.user.id; + const alerts = await this.service.list(userId); + res.json(alerts); + }; + this.markAsRead = async (req, res) => { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + const userId = req.user.id; + const alertId = Number(req.params.id); + if (!alertId) { + throw new Error("Article not found"); + } + const success = await this.service.read(alertId, userId); + if (!success) { + return res.status(http_status_1.default.FORBIDDEN).json({ + message: "You do not have permission to read this alert", + }); + } + res.status(204).send(); + }; + } +} +exports.AlertController = AlertController; +//# sourceMappingURL=alertController.js.map \ No newline at end of file diff --git a/mission 10/dist/controllers/alertController.js.map b/mission 10/dist/controllers/alertController.js.map new file mode 100644 index 000000000..0546cdc46 --- /dev/null +++ b/mission 10/dist/controllers/alertController.js.map @@ -0,0 +1 @@ +{"version":3,"file":"alertController.js","sourceRoot":"","sources":["../../src/controllers/alertController.ts"],"names":[],"mappings":";;;;;;AACA,2DAAwD;AACxD,8DAAiC;AAEjC,MAAa,eAAe;IAA5B;QACU,YAAO,GAAG,IAAI,2BAAY,EAAE,CAAC;QAErC,SAAI,GAAG,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;YAC3C,IAAI,CAAC,GAAG,CAAC,IAAI;gBACX,OAAO,GAAG,CAAC,MAAM,CAAC,qBAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;YAC3E,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC/C,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC,CAAC;QAEF,eAAU,GAAG,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;YACjD,IAAI,CAAC,GAAG,CAAC,IAAI;gBACX,OAAO,GAAG,CAAC,MAAM,CAAC,qBAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;YAE3E,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAEtC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACvC,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAEzD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,GAAG,CAAC,MAAM,CAAC,qBAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC;oBACvC,OAAO,EAAE,+CAA+C;iBACzD,CAAC,CAAC;YACL,CAAC;YACD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QACzB,CAAC,CAAC;IACJ,CAAC;CAAA;AA/BD,0CA+BC"} \ No newline at end of file diff --git a/mission 10/dist/controllers/articleController.js b/mission 10/dist/controllers/articleController.js new file mode 100644 index 000000000..ded6056e7 --- /dev/null +++ b/mission 10/dist/controllers/articleController.js @@ -0,0 +1,81 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ArticleController = void 0; +const http_status_1 = __importDefault(require("http-status")); +const articleService_1 = require("../services/articleService"); +const article_dto_1 = require("../dtos/article.dto"); +const articleService = new articleService_1.ArticleService(); +class ArticleController { + async create(req, res, next) { + try { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = article_dto_1.ArticleCreateSchema.parse(req.body); + const article = await articleService.create(req.user.id, parsed); + res.status(http_status_1.default.CREATED).json(article); + } + catch (err) { + next(err); + } + } + async list(req, res, next) { + try { + const parsed = article_dto_1.ArticleQuerySchema.parse(req.query); + const articles = await articleService.list(parsed); + res.status(http_status_1.default.OK).json(articles); + } + catch (err) { + next(err); + } + } + async detail(req, res, next) { + try { + const articleId = Number(req.params.id); + const article = await articleService.getDetail(articleId); + if (!article) + return res.status(http_status_1.default.NOT_FOUND).json({ message: "Article not found" }); + res.status(http_status_1.default.OK).json(article); + } + catch (err) { + next(err); + } + } + async update(req, res, next) { + try { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = article_dto_1.ArticleUpdateSchema.parse(req.body); + const articleId = Number(req.params.id); + const updated = await articleService.update(req.user.id, parsed, articleId); + res.status(http_status_1.default.OK).json(updated); + } + catch (err) { + if (err.message === "NOT_FOUND") + return res.status(http_status_1.default.NOT_FOUND).json({ message: "Article not found" }); + if (err.message === "FORBIDDEN") + return res.status(http_status_1.default.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + async delete(req, res, next) { + try { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + const articleId = Number(req.params.id); + await articleService.delete(req.user.id, articleId); + res.status(http_status_1.default.NO_CONTENT).end(); + } + catch (err) { + if (err.message === "NOT_FOUND") + return res.status(http_status_1.default.NOT_FOUND).json({ message: "Article not found" }); + if (err.message === "FORBIDDEN") + return res.status(http_status_1.default.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } +} +exports.ArticleController = ArticleController; +//# sourceMappingURL=articleController.js.map \ No newline at end of file diff --git a/mission 10/dist/controllers/articleController.js.map b/mission 10/dist/controllers/articleController.js.map new file mode 100644 index 000000000..b6bf36d39 --- /dev/null +++ b/mission 10/dist/controllers/articleController.js.map @@ -0,0 +1 @@ +{"version":3,"file":"articleController.js","sourceRoot":"","sources":["../../src/controllers/articleController.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/mission 10/dist/controllers/commentController.js b/mission 10/dist/controllers/commentController.js new file mode 100644 index 000000000..aceaefb03 --- /dev/null +++ b/mission 10/dist/controllers/commentController.js @@ -0,0 +1,100 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CommentController = void 0; +const zod_1 = require("zod"); +const http_status_1 = __importDefault(require("http-status")); +const commentService_1 = require("../services/commentService"); +const commentService = new commentService_1.CommentService(); +const commentSchema = zod_1.z.object({ + content: zod_1.z.string().min(5).max(100), +}); +const commentListSchema = zod_1.z.object({ + id: zod_1.z.coerce.number().int().positive(), + lastId: zod_1.z.coerce.number().int().positive().optional(), +}); +class CommentController { + async createProductComment(req, res, next) { + try { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + const productId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const comment = await commentService.createProductComment(req.user.id, productId, parsed.content); + res.status(http_status_1.default.CREATED).json(comment); + } + catch (err) { + next(err); + } + } + async createArticleComment(req, res, next) { + try { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + const articleId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const comment = await commentService.createArticleComment(req.user.id, articleId, parsed.content); + res.status(http_status_1.default.CREATED).json(comment); + } + catch (err) { + next(err); + } + } + async modifyComment(req, res, next) { + try { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + const commentId = Number(req.params.id); + const parsed = commentSchema.parse(req.body); + const updated = await commentService.updateComment(req.user.id, commentId, parsed.content); + res.status(http_status_1.default.OK).json(updated); + } + catch (err) { + if (err.message === "NOT_FOUND") + return res.status(http_status_1.default.NOT_FOUND).json({ message: "Comment not found" }); + if (err.message === "FORBIDDEN") + return res.status(http_status_1.default.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + async deleteComment(req, res, next) { + try { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + const commentId = Number(req.params.id); + await commentService.deleteComment(req.user.id, commentId); + res.status(http_status_1.default.NO_CONTENT).end(); + } + catch (err) { + if (err.message === "NOT_FOUND") + return res.status(http_status_1.default.NOT_FOUND).json({ message: "Comment not found" }); + if (err.message === "FORBIDDEN") + return res.status(http_status_1.default.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + async productCommentList(req, res, next) { + try { + const parsed = commentListSchema.parse({ id: req.params.id, lastId: req.query.lastId }); + const comments = await commentService.getProductComments(parsed.id, parsed.lastId); + res.status(http_status_1.default.OK).json(comments); + } + catch (err) { + next(err); + } + } + async articleCommentList(req, res, next) { + try { + const parsed = commentListSchema.parse({ id: req.params.id, lastId: req.query.lastId }); + const comments = await commentService.getArticleComments(parsed.id, parsed.lastId); + res.status(http_status_1.default.OK).json(comments); + } + catch (err) { + next(err); + } + } +} +exports.CommentController = CommentController; +//# sourceMappingURL=commentController.js.map \ No newline at end of file diff --git a/mission 10/dist/controllers/commentController.js.map b/mission 10/dist/controllers/commentController.js.map new file mode 100644 index 000000000..d122de1f9 --- /dev/null +++ b/mission 10/dist/controllers/commentController.js.map @@ -0,0 +1 @@ +{"version":3,"file":"commentController.js","sourceRoot":"","sources":["../../src/controllers/commentController.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/mission 10/dist/controllers/likeController.js b/mission 10/dist/controllers/likeController.js new file mode 100644 index 000000000..07578b0bf --- /dev/null +++ b/mission 10/dist/controllers/likeController.js @@ -0,0 +1,63 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LikeController = void 0; +const http_status_1 = __importDefault(require("http-status")); +const likeService_1 = require("../services/likeService"); +const likeService = new likeService_1.LikeService(); +class LikeController { + async likeArticle(req, res, next) { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const result = await likeService.likeArticle(req.user.id, Number(req.params.id)); + res.status(http_status_1.default.OK).json({ message: "Like toggled", isLiked: result.like }); + } + catch (err) { + if (err.message === "ARTICLE_NOT_FOUND") + return res.status(http_status_1.default.NOT_FOUND).json({ message: "Article not found" }); + next(err); + } + } + async likeProduct(req, res, next) { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const result = await likeService.likeProduct(req.user.id, Number(req.params.id)); + res.status(http_status_1.default.OK).json({ message: "Like toggled", isLiked: result.like }); + } + catch (err) { + if (err.message === "PRODUCT_NOT_FOUND") + return res.status(http_status_1.default.NOT_FOUND).json({ message: "Product not found" }); + next(err); + } + } + async getLikedArticles(req, res, next) { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const likedArticles = await likeService.getLikedArticles(req.user.id); + const articles = likedArticles.map((l) => ({ ...l.article, isLiked: true })); + res.status(http_status_1.default.OK).json(articles); + } + catch (err) { + next(err); + } + } + async getLikedProducts(req, res, next) { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const likedProducts = await likeService.getLikedProducts(req.user.id); + const products = likedProducts.map((l) => ({ ...l.product, isLiked: true })); + res.status(http_status_1.default.OK).json(products); + } + catch (err) { + next(err); + } + } +} +exports.LikeController = LikeController; +//# sourceMappingURL=likeController.js.map \ No newline at end of file diff --git a/mission 10/dist/controllers/likeController.js.map b/mission 10/dist/controllers/likeController.js.map new file mode 100644 index 000000000..02dd2d21c --- /dev/null +++ b/mission 10/dist/controllers/likeController.js.map @@ -0,0 +1 @@ +{"version":3,"file":"likeController.js","sourceRoot":"","sources":["../../src/controllers/likeController.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/mission 10/dist/controllers/photoController.js b/mission 10/dist/controllers/photoController.js new file mode 100644 index 000000000..8de6b61f2 --- /dev/null +++ b/mission 10/dist/controllers/photoController.js @@ -0,0 +1,33 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.PhotoController = void 0; +const prisma_1 = __importDefault(require("../lib/prisma")); +const http_status_1 = __importDefault(require("http-status")); +class PhotoController { + async upload(req, res, next) { + if (!req.user) + return res.status(401).json({ message: "Unauthorized" }); + if (!req.file) { + return res.status(http_status_1.default.BAD_REQUEST).json({ message: "No file uploaded" }); + } + try { + const imageUrl = req.file.location; + const updatedUser = await prisma_1.default.user.update({ + where: { id: req.user.id }, + data: { image: imageUrl }, + }); + res.status(http_status_1.default.OK).json({ + message: "Photo uploaded successfully", + image: updatedUser.image, + }); + } + catch (err) { + next(err); + } + } +} +exports.PhotoController = PhotoController; +//# sourceMappingURL=photoController.js.map \ No newline at end of file diff --git a/mission 10/dist/controllers/photoController.js.map b/mission 10/dist/controllers/photoController.js.map new file mode 100644 index 000000000..67da44fb9 --- /dev/null +++ b/mission 10/dist/controllers/photoController.js.map @@ -0,0 +1 @@ +{"version":3,"file":"photoController.js","sourceRoot":"","sources":["../../src/controllers/photoController.ts"],"names":[],"mappings":";;;;;;AACA,2DAAmC;AACnC,8DAAiC;AAEjC,MAAa,eAAe;IAC1B,KAAK,CAAC,MAAM,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;QAC1D,IAAI,CAAC,GAAG,CAAC,IAAI;YAAE,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;QAExE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,GAAG,CAAC,MAAM,CAAC,qBAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC9E,CAAC;QAED,IAAI,CAAC;YACH,MAAM,QAAQ,GAAI,GAAG,CAAC,IAAY,CAAC,QAAQ,CAAC;YAE5C,MAAM,WAAW,GAAG,MAAM,gBAAM,CAAC,IAAI,CAAC,MAAM,CAAC;gBAC3C,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE;gBAC1B,IAAI,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE;aAC1B,CAAC,CAAC;YAEH,GAAG,CAAC,MAAM,CAAC,qBAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC;gBACzB,OAAO,EAAE,6BAA6B;gBACtC,KAAK,EAAE,WAAW,CAAC,KAAK;aACzB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,CAAC;QACZ,CAAC;IACH,CAAC;CACF;AAxBD,0CAwBC"} \ No newline at end of file diff --git a/mission 10/dist/controllers/productController.js b/mission 10/dist/controllers/productController.js new file mode 100644 index 000000000..ebe735712 --- /dev/null +++ b/mission 10/dist/controllers/productController.js @@ -0,0 +1,81 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ProductController = void 0; +const http_status_1 = __importDefault(require("http-status")); +const productService_1 = require("../services/productService"); +const product_dto_1 = require("../dtos/product.dto"); +const productService = new productService_1.ProductService(); +class ProductController { + async create(req, res, next) { + try { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = product_dto_1.ProductCreateSchema.parse(req.body); + const product = await productService.create(req.user.id, parsed); + res.status(http_status_1.default.CREATED).json(product); + } + catch (err) { + next(err); + } + } + async list(req, res, next) { + try { + const parsed = product_dto_1.ProductQuerySchema.parse(req.query); + const products = await productService.list(parsed); + res.status(http_status_1.default.OK).json(products); + } + catch (err) { + next(err); + } + } + async detail(req, res, next) { + try { + const productId = Number(req.params.id); + const product = await productService.getDetail(productId); + if (!product) + return res.status(http_status_1.default.NOT_FOUND).json({ message: "Product not found" }); + res.status(http_status_1.default.OK).json(product); + } + catch (err) { + next(err); + } + } + async update(req, res, next) { + try { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = product_dto_1.ProductUpdateSchema.parse(req.body); + const productId = Number(req.params.id); + const updated = await productService.update(req.user.id, productId, parsed); + res.status(http_status_1.default.OK).json(updated); + } + catch (err) { + if (err.message === "NOT_FOUND") + return res.status(http_status_1.default.NOT_FOUND).json({ message: "Product not found" }); + if (err.message === "FORBIDDEN") + return res.status(http_status_1.default.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } + async delete(req, res, next) { + try { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + const productId = Number(req.params.id); + await productService.delete(req.user.id, productId); + res.status(http_status_1.default.NO_CONTENT).end(); + } + catch (err) { + if (err.message === "NOT_FOUND") + return res.status(http_status_1.default.NOT_FOUND).json({ message: "Product not found" }); + if (err.message === "FORBIDDEN") + return res.status(http_status_1.default.FORBIDDEN).json({ message: "User not matched" }); + next(err); + } + } +} +exports.ProductController = ProductController; +//# sourceMappingURL=productController.js.map \ No newline at end of file diff --git a/mission 10/dist/controllers/productController.js.map b/mission 10/dist/controllers/productController.js.map new file mode 100644 index 000000000..99bc9e254 --- /dev/null +++ b/mission 10/dist/controllers/productController.js.map @@ -0,0 +1 @@ +{"version":3,"file":"productController.js","sourceRoot":"","sources":["../../src/controllers/productController.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/mission 10/dist/controllers/userController.js b/mission 10/dist/controllers/userController.js new file mode 100644 index 000000000..e2f9d7a6c --- /dev/null +++ b/mission 10/dist/controllers/userController.js @@ -0,0 +1,102 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UserController = void 0; +const http_status_1 = __importDefault(require("http-status")); +const userService_1 = require("../services/userService"); +const cookieUtil_1 = require("../lib/cookieUtil"); +const user_dto_1 = require("../dtos/user.dto"); +const userService = new userService_1.UserService(); +class UserController { + async register(req, res, next) { + try { + const parsed = user_dto_1.UserRegisterSchema.parse(req.body); + const result = await userService.register(parsed); + res.status(http_status_1.default.CREATED).json(result); + } + catch (err) { + if (err.message === "EMAIL_EXISTS") { + return res.status(http_status_1.default.CONFLICT).json({ message: "This ID already exists" }); + } + next(err); + } + } + login(req, res, next) { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + try { + const { accessToken, refreshToken } = userService.generateUserTokens(req.user.id); + (0, cookieUtil_1.setTokenCookies)(res, accessToken, refreshToken); + res.status(http_status_1.default.OK).json({ accessToken, refreshToken }); + } + catch (err) { + next(err); + } + } + async profile(req, res, next) { + try { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + const profile = await userService.getProfile(req.user.id); + res.status(http_status_1.default.OK).json(profile); + } + catch (err) { + next(err); + } + } + async modifyInformation(req, res, next) { + try { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = user_dto_1.UserUpdateSchema.parse(req.body); // DTO 검증 + const updatedUser = await userService.updateInformation(req.user.id, parsed.nickname, parsed.image); + res.status(http_status_1.default.OK).json({ message: "User information updated successfully", user: updatedUser }); + } + catch (err) { + if (err.message === "NO_DATA") + return res.status(http_status_1.default.BAD_REQUEST).json({ message: "No update data provided" }); + next(err); + } + } + async modifyPassword(req, res, next) { + try { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + const parsed = user_dto_1.UserPasswordSchema.parse(req.body); // DTO 검증 + const result = await userService.updatePassword(req.user.id, parsed); + res.status(http_status_1.default.OK).json(result); + } + catch (err) { + next(err); + } + } + async products(req, res, next) { + try { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + const products = await userService.getProducts(req.user.id); + if (!products || products.length === 0) { + return res.status(http_status_1.default.NOT_FOUND).json({ message: "No product" }); + } + res.status(http_status_1.default.OK).json(products); + } + catch (err) { + next(err); + } + } + refreshTokens(req, res) { + if (!req.user) + return res.status(http_status_1.default.UNAUTHORIZED).json({ message: "Unauthorized" }); + const { accessToken, refreshToken } = userService.generateUserTokens(req.user.id); + (0, cookieUtil_1.setTokenCookies)(res, accessToken, refreshToken); + res.status(http_status_1.default.OK).send({ message: "Tokens refreshed" }); + } + logout(req, res) { + (0, cookieUtil_1.clearTokenCookies)(res); + res.status(http_status_1.default.OK).send({ message: "Logged out successfully" }); + } +} +exports.UserController = UserController; +//# sourceMappingURL=userController.js.map \ No newline at end of file diff --git a/mission 10/dist/controllers/userController.js.map b/mission 10/dist/controllers/userController.js.map new file mode 100644 index 000000000..87c74f635 --- /dev/null +++ b/mission 10/dist/controllers/userController.js.map @@ -0,0 +1 @@ +{"version":3,"file":"userController.js","sourceRoot":"","sources":["../../src/controllers/userController.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/mission 10/dist/dtos/article.dto.js b/mission 10/dist/dtos/article.dto.js new file mode 100644 index 000000000..f4433a370 --- /dev/null +++ b/mission 10/dist/dtos/article.dto.js @@ -0,0 +1,36 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ArticleQuerySchema = exports.ArticleUpdateSchema = exports.ArticleCreateSchema = void 0; +const zod_1 = require("zod"); +// CREATE DTO +exports.ArticleCreateSchema = zod_1.z.object({ + title: zod_1.z.string().min(1, { message: "제목을 입력해주세요" }), + content: zod_1.z + .string() + .min(10, { message: "내용은 최소 10자 이상이어야 합니다." }) + .max(200, { message: "내용은 최대 200자까지 가능합니다." }), +}); +// UPDATE DTO (PATCH) +exports.ArticleUpdateSchema = zod_1.z.object({ + title: zod_1.z.string().min(1, { message: "제목을 입력해주세요" }).optional(), + content: zod_1.z + .string() + .min(10, { message: "내용은 최소 10자 이상이어야 합니다." }) + .max(200, { message: "내용은 최대 200자까지 가능합니다." }) + .optional(), +}); +// QUERY DTO (GET /articles) +exports.ArticleQuerySchema = zod_1.z.object({ + page: zod_1.z + .string() + .default("1") + .transform(Number) + .refine((val) => val > 0, { message: "page는 1 이상의 정수여야 합니다." }), + pageSize: zod_1.z + .string() + .default("5") + .transform(Number) + .refine((val) => val > 0 && val <= 100, { message: "pageSize는 1~100 사이여야 합니다." }), + keyword: zod_1.z.string().default(""), +}); +//# sourceMappingURL=article.dto.js.map \ No newline at end of file diff --git a/mission 10/dist/dtos/article.dto.js.map b/mission 10/dist/dtos/article.dto.js.map new file mode 100644 index 000000000..6469a2d17 --- /dev/null +++ b/mission 10/dist/dtos/article.dto.js.map @@ -0,0 +1 @@ +{"version":3,"file":"article.dto.js","sourceRoot":"","sources":["../../src/dtos/article.dto.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AAExB,aAAa;AACA,QAAA,mBAAmB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC1C,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;IACnD,OAAO,EAAE,OAAC;SACP,MAAM,EAAE;SACR,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC;SAC7C,GAAG,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;CACjD,CAAC,CAAC;AAGH,qBAAqB;AACR,QAAA,mBAAmB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC1C,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC9D,OAAO,EAAE,OAAC;SACP,MAAM,EAAE;SACR,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC;SAC7C,GAAG,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;SAC7C,QAAQ,EAAE;CACd,CAAC,CAAC;AAGH,4BAA4B;AACf,QAAA,kBAAkB,GAAG,OAAC,CAAC,MAAM,CAAC;IACzC,IAAI,EAAE,OAAC;SACJ,MAAM,EAAE;SACR,OAAO,CAAC,GAAG,CAAC;SACZ,SAAS,CAAC,MAAM,CAAC;SACjB,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC;IACjE,QAAQ,EAAE,OAAC;SACR,MAAM,EAAE;SACR,OAAO,CAAC,GAAG,CAAC;SACZ,SAAS,CAAC,MAAM,CAAC;SACjB,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,IAAI,GAAG,EAAE,EAAE,OAAO,EAAE,2BAA2B,EAAE,CAAC;IACnF,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;CAChC,CAAC,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/dtos/product.dto.js b/mission 10/dist/dtos/product.dto.js new file mode 100644 index 000000000..8a307560a --- /dev/null +++ b/mission 10/dist/dtos/product.dto.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ProductQuerySchema = exports.ProductUpdateSchema = exports.ProductCreateSchema = void 0; +const zod_1 = require("zod"); +// CREATE DTO +exports.ProductCreateSchema = zod_1.z.object({ + name: zod_1.z.string().min(1, { message: "이름을 입력해주세요" }), + description: zod_1.z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }), + price: zod_1.z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }), + tags: zod_1.z.string().default(""), +}); +// UPDATE DTO +exports.ProductUpdateSchema = zod_1.z.object({ + name: zod_1.z.string().min(1, { message: "이름을 입력해주세요" }).optional(), + description: zod_1.z.string().min(10, { message: "설명은 최소 10자 이상" }).max(100, { message: "설명은 최대 100자" }).optional(), + price: zod_1.z.number().int().positive({ message: "가격은 양의 정수여야 합니다." }).optional(), + tags: zod_1.z.string().default("").optional(), +}); +// QUERY DTO +exports.ProductQuerySchema = zod_1.z.object({ + page: zod_1.z.string().default("1").transform(Number).refine((v) => v > 0), + pageSize: zod_1.z.string().default("5").transform(Number).refine((v) => v > 0 && v <= 100), + keyword: zod_1.z.string().default(""), +}); +//# sourceMappingURL=product.dto.js.map \ No newline at end of file diff --git a/mission 10/dist/dtos/product.dto.js.map b/mission 10/dist/dtos/product.dto.js.map new file mode 100644 index 000000000..3f305a9e0 --- /dev/null +++ b/mission 10/dist/dtos/product.dto.js.map @@ -0,0 +1 @@ +{"version":3,"file":"product.dto.js","sourceRoot":"","sources":["../../src/dtos/product.dto.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AAGxB,cAAc;AACD,QAAA,mBAAmB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC1C,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;IAClD,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;IAClG,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC;IACjE,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;CAC7B,CAAC,CAAC;AAGH,aAAa;AACA,QAAA,mBAAmB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC1C,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC7D,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC7G,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC5E,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;CACxC,CAAC,CAAC;AAGH,YAAY;AACC,QAAA,kBAAkB,GAAG,OAAC,CAAC,MAAM,CAAC;IACzC,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;IACpE,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC;IACpF,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;CAChC,CAAC,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/dtos/user.dto.js b/mission 10/dist/dtos/user.dto.js new file mode 100644 index 000000000..988032d3a --- /dev/null +++ b/mission 10/dist/dtos/user.dto.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UserPasswordSchema = exports.UserUpdateSchema = exports.UserLoginSchema = exports.UserRegisterSchema = void 0; +const zod_1 = require("zod"); +// 회원가입 +exports.UserRegisterSchema = zod_1.z.object({ + email: zod_1.z.string().email({ message: "Invalid email" }), + nickname: zod_1.z.string().min(2, { message: "Nickname too short" }), + password: zod_1.z.string().min(6, { message: "Password too short" }), +}); +// 로그인 +exports.UserLoginSchema = zod_1.z.object({ + email: zod_1.z.string().email(), + password: zod_1.z.string().min(6), +}); +// 정보 수정 (PATCH) +exports.UserUpdateSchema = zod_1.z.object({ + nickname: zod_1.z.string().min(2).optional(), + image: zod_1.z.string().url().optional(), +}); +// 비밀번호 수정 +exports.UserPasswordSchema = zod_1.z.object({ + password: zod_1.z.string().min(6, { message: "Password too short" }), +}); +//# sourceMappingURL=user.dto.js.map \ No newline at end of file diff --git a/mission 10/dist/dtos/user.dto.js.map b/mission 10/dist/dtos/user.dto.js.map new file mode 100644 index 000000000..4d231eb95 --- /dev/null +++ b/mission 10/dist/dtos/user.dto.js.map @@ -0,0 +1 @@ +{"version":3,"file":"user.dto.js","sourceRoot":"","sources":["../../src/dtos/user.dto.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AAExB,OAAO;AACM,QAAA,kBAAkB,GAAG,OAAC,CAAC,MAAM,CAAC;IACzC,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;IACrD,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAC9D,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC;CAC/D,CAAC,CAAC;AAGH,MAAM;AACO,QAAA,eAAe,GAAG,OAAC,CAAC,MAAM,CAAC;IACtC,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE;IACzB,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC5B,CAAC,CAAC;AAGH,gBAAgB;AACH,QAAA,gBAAgB,GAAG,OAAC,CAAC,MAAM,CAAC;IACvC,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACtC,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;CACnC,CAAC,CAAC;AAGH,UAAU;AACG,QAAA,kBAAkB,GAAG,OAAC,CAAC,MAAM,CAAC;IACzC,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC;CAC/D,CAAC,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/lib/constants.js b/mission 10/dist/lib/constants.js new file mode 100644 index 000000000..c8ae7ba01 --- /dev/null +++ b/mission 10/dist/lib/constants.js @@ -0,0 +1,21 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.REFRESH_TOKEN_COOKIE_NAME = exports.ACCESS_TOKEN_COOKIE_NAME = exports.JWT_REFRESH_TOKEN_SECRET = exports.JWT_ACCESS_TOKEN_SECRET = exports.PORT = exports.NODE_ENV = void 0; +const dotenv_1 = __importDefault(require("dotenv")); +dotenv_1.default.config(); +const NODE_ENV = process.env.NODE_ENV || 'development'; +exports.NODE_ENV = NODE_ENV; +const PORT = process.env.PORT || 3000; +exports.PORT = PORT; +const JWT_ACCESS_TOKEN_SECRET = process.env.JWT_ACCESS_TOKEN_SECRET || 'your_jwt_access_token_secret'; +exports.JWT_ACCESS_TOKEN_SECRET = JWT_ACCESS_TOKEN_SECRET; +const JWT_REFRESH_TOKEN_SECRET = process.env.JWT_REFRESH_TOKEN_SECRET || 'your_jwt_refresh_token_secret'; +exports.JWT_REFRESH_TOKEN_SECRET = JWT_REFRESH_TOKEN_SECRET; +const ACCESS_TOKEN_COOKIE_NAME = 'access-token'; +exports.ACCESS_TOKEN_COOKIE_NAME = ACCESS_TOKEN_COOKIE_NAME; +const REFRESH_TOKEN_COOKIE_NAME = 'refresh-token'; +exports.REFRESH_TOKEN_COOKIE_NAME = REFRESH_TOKEN_COOKIE_NAME; +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/mission 10/dist/lib/constants.js.map b/mission 10/dist/lib/constants.js.map new file mode 100644 index 000000000..16a5be698 --- /dev/null +++ b/mission 10/dist/lib/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":";;;;;;AAAA,oDAA4B;AAE5B,gBAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa,CAAC;AAUrD,4BAAQ;AATV,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;AAUpC,oBAAI;AATN,MAAM,uBAAuB,GAC3B,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,8BAA8B,CAAC;AAStE,0DAAuB;AARzB,MAAM,wBAAwB,GAC5B,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,+BAA+B,CAAC;AAQxE,4DAAwB;AAP1B,MAAM,wBAAwB,GAAG,cAAc,CAAC;AAQ9C,4DAAwB;AAP1B,MAAM,yBAAyB,GAAG,eAAe,CAAC;AAQhD,8DAAyB"} \ No newline at end of file diff --git a/mission 10/dist/lib/cookieUtil.js b/mission 10/dist/lib/cookieUtil.js new file mode 100644 index 000000000..761480cb0 --- /dev/null +++ b/mission 10/dist/lib/cookieUtil.js @@ -0,0 +1,23 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.setTokenCookies = setTokenCookies; +exports.clearTokenCookies = clearTokenCookies; +const constants_1 = require("./constants"); +function setTokenCookies(res, accessToken, refreshToken) { + res.cookie(constants_1.ACCESS_TOKEN_COOKIE_NAME, accessToken, { + httpOnly: true, + secure: constants_1.NODE_ENV === "production", + maxAge: 1 * 60 * 60 * 1000, // 1시간 + }); + res.cookie(constants_1.REFRESH_TOKEN_COOKIE_NAME, refreshToken, { + httpOnly: true, + secure: constants_1.NODE_ENV === "production", + maxAge: 7 * 24 * 60 * 60 * 1000, // 7일 + path: "/users/refresh", + }); +} +function clearTokenCookies(res) { + res.clearCookie(constants_1.ACCESS_TOKEN_COOKIE_NAME); + res.clearCookie(constants_1.REFRESH_TOKEN_COOKIE_NAME); +} +//# sourceMappingURL=cookieUtil.js.map \ No newline at end of file diff --git a/mission 10/dist/lib/cookieUtil.js.map b/mission 10/dist/lib/cookieUtil.js.map new file mode 100644 index 000000000..3e47cfbbb --- /dev/null +++ b/mission 10/dist/lib/cookieUtil.js.map @@ -0,0 +1 @@ +{"version":3,"file":"cookieUtil.js","sourceRoot":"","sources":["../../src/lib/cookieUtil.ts"],"names":[],"mappings":";;AAGA,0CAaC;AAED,8CAGC;AApBD,2CAA4F;AAE5F,SAAgB,eAAe,CAAC,GAAa,EAAE,WAAmB,EAAE,YAAoB;IACtF,GAAG,CAAC,MAAM,CAAC,oCAAwB,EAAE,WAAW,EAAE;QAChD,QAAQ,EAAE,IAAI;QACd,MAAM,EAAE,oBAAQ,KAAK,YAAY;QACjC,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,MAAM;KACnC,CAAC,CAAC;IAEH,GAAG,CAAC,MAAM,CAAC,qCAAyB,EAAE,YAAY,EAAE;QAClD,QAAQ,EAAE,IAAI;QACd,MAAM,EAAE,oBAAQ,KAAK,YAAY;QACjC,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,KAAK;QACtC,IAAI,EAAE,gBAAgB;KACvB,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,iBAAiB,CAAC,GAAa;IAC7C,GAAG,CAAC,WAAW,CAAC,oCAAwB,CAAC,CAAC;IAC1C,GAAG,CAAC,WAAW,CAAC,qCAAyB,CAAC,CAAC;AAC7C,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/lib/passport/index.js b/mission 10/dist/lib/passport/index.js new file mode 100644 index 000000000..9bb73bd1a --- /dev/null +++ b/mission 10/dist/lib/passport/index.js @@ -0,0 +1,13 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const passport_1 = __importDefault(require("passport")); +const localStrategy_1 = require("./localStrategy"); +const jwtStrategy_1 = require("./jwtStrategy"); +passport_1.default.use('local', localStrategy_1.localStrategy); +passport_1.default.use('access-token', jwtStrategy_1.accessTokenStrategy); +passport_1.default.use('refresh-token', jwtStrategy_1.refreshTokenStrategy); +exports.default = passport_1.default; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/mission 10/dist/lib/passport/index.js.map b/mission 10/dist/lib/passport/index.js.map new file mode 100644 index 000000000..a55bc1180 --- /dev/null +++ b/mission 10/dist/lib/passport/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/passport/index.ts"],"names":[],"mappings":";;;;;AAAA,wDAAgC;AAChC,mDAAgD;AAChD,+CAA0E;AAE1E,kBAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,6BAAa,CAAC,CAAC;AACrC,kBAAQ,CAAC,GAAG,CAAC,cAAc,EAAE,iCAAmB,CAAC,CAAC;AAClD,kBAAQ,CAAC,GAAG,CAAC,eAAe,EAAE,kCAAoB,CAAC,CAAC;AAEpD,kBAAe,kBAAQ,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/lib/passport/jwtStrategy.js b/mission 10/dist/lib/passport/jwtStrategy.js new file mode 100644 index 000000000..da94d3bf1 --- /dev/null +++ b/mission 10/dist/lib/passport/jwtStrategy.js @@ -0,0 +1,37 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.refreshTokenStrategy = exports.accessTokenStrategy = void 0; +const passport_jwt_1 = require("passport-jwt"); +const prisma_1 = __importDefault(require("../prisma")); +const constants_1 = require("../constants"); +// const accessTokenOptions = { +// jwtFromRequest: (req: Request) => req.cookies[ACCESS_TOKEN_COOKIE_NAME], +// secretOrKey: JWT_ACCESS_TOKEN_SECRET, +// }; +const accessTokenOptions = { + jwtFromRequest: (req) => { + return req.cookies[constants_1.ACCESS_TOKEN_COOKIE_NAME] || passport_jwt_1.ExtractJwt.fromAuthHeaderAsBearerToken()(req); + }, + secretOrKey: constants_1.JWT_ACCESS_TOKEN_SECRET, +}; +const refreshTokenOptions = { + jwtFromRequest: (req) => req.cookies[constants_1.REFRESH_TOKEN_COOKIE_NAME], + secretOrKey: constants_1.JWT_REFRESH_TOKEN_SECRET, +}; +async function jwtVerify(payload, done) { + try { + const user = await prisma_1.default.user.findUnique({ + where: { id: payload.sub }, + }); + done(null, user); + } + catch (error) { + done(error, false); + } +} +exports.accessTokenStrategy = new passport_jwt_1.Strategy(accessTokenOptions, jwtVerify); +exports.refreshTokenStrategy = new passport_jwt_1.Strategy(refreshTokenOptions, jwtVerify); +//# sourceMappingURL=jwtStrategy.js.map \ No newline at end of file diff --git a/mission 10/dist/lib/passport/jwtStrategy.js.map b/mission 10/dist/lib/passport/jwtStrategy.js.map new file mode 100644 index 000000000..c5d0fb51c --- /dev/null +++ b/mission 10/dist/lib/passport/jwtStrategy.js.map @@ -0,0 +1 @@ +{"version":3,"file":"jwtStrategy.js","sourceRoot":"","sources":["../../../src/lib/passport/jwtStrategy.ts"],"names":[],"mappings":";;;;;;AAAA,+CAAmE;AACnE,uDAA+B;AAG/B,4CAKsB;AAMtB,+BAA+B;AAC/B,6EAA6E;AAC7E,0CAA0C;AAC1C,KAAK;AAEL,MAAM,kBAAkB,GAAG;IACzB,cAAc,EAAE,CAAC,GAAY,EAAE,EAAE;QAC/B,OAAO,GAAG,CAAC,OAAO,CAAC,oCAAwB,CAAC,IAAI,yBAAU,CAAC,2BAA2B,EAAE,CAAC,GAAG,CAAC,CAAC;IAChG,CAAC;IACD,WAAW,EAAE,mCAAuB;CACrC,CAAC;AAEF,MAAM,mBAAmB,GAAG;IAC1B,cAAc,EAAE,CAAC,GAAY,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,qCAAyB,CAAC;IACxE,WAAW,EAAE,oCAAwB;CACtC,CAAC;AAEF,KAAK,UAAU,SAAS,CAAC,OAAmB,EAAE,IAAsB;IAClE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,gBAAM,CAAC,IAAI,CAAC,UAAU,CAAC;YACxC,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,GAAG,EAAE;SAC3B,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACnB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACrB,CAAC;AACH,CAAC;AAEY,QAAA,mBAAmB,GAAG,IAAI,uBAAW,CAChD,kBAAkB,EAClB,SAAS,CACV,CAAC;AAEW,QAAA,oBAAoB,GAAG,IAAI,uBAAW,CACjD,mBAAmB,EACnB,SAAS,CACV,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/lib/passport/localStrategy.js b/mission 10/dist/lib/passport/localStrategy.js new file mode 100644 index 000000000..af51241cb --- /dev/null +++ b/mission 10/dist/lib/passport/localStrategy.js @@ -0,0 +1,29 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.localStrategy = void 0; +const passport_local_1 = require("passport-local"); +const bcrypt_1 = __importDefault(require("bcrypt")); +const prisma_1 = __importDefault(require("../prisma")); +exports.localStrategy = new passport_local_1.Strategy({ + usernameField: "email", // email을 localStrategy의 고정값 'username' 대신 쓰도록 지정 + passwordField: "password", +}, async (email, password, done) => { + try { + const user = await prisma_1.default.user.findUnique({ where: { email } }); + if (!user) { + return done(null, false, { message: "No user found" }); + } + const isPasswordValid = await bcrypt_1.default.compare(password, user.password); + if (!isPasswordValid) { + return done(null, false, { message: "Invalid password" }); + } + return done(null, user); + } + catch (err) { + return done(err); + } +}); +//# sourceMappingURL=localStrategy.js.map \ No newline at end of file diff --git a/mission 10/dist/lib/passport/localStrategy.js.map b/mission 10/dist/lib/passport/localStrategy.js.map new file mode 100644 index 000000000..8502f7428 --- /dev/null +++ b/mission 10/dist/lib/passport/localStrategy.js.map @@ -0,0 +1 @@ +{"version":3,"file":"localStrategy.js","sourceRoot":"","sources":["../../../src/lib/passport/localStrategy.ts"],"names":[],"mappings":";;;;;;AAAA,mDAA2D;AAC3D,oDAA4B;AAC5B,uDAA+B;AAElB,QAAA,aAAa,GAAG,IAAI,yBAAa,CAC5C;IACE,aAAa,EAAE,OAAO,EAAE,iDAAiD;IACzE,aAAa,EAAE,UAAU;CAC1B,EACD,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;IAC9B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,gBAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC;QACzD,CAAC;QAED,MAAM,eAAe,GAAG,MAAM,gBAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtE,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC5D,CAAC;QAED,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CACF,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/lib/prisma.js b/mission 10/dist/lib/prisma.js new file mode 100644 index 000000000..cb7a5ecb5 --- /dev/null +++ b/mission 10/dist/lib/prisma.js @@ -0,0 +1,6 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const client_1 = require("@prisma/client"); +const prisma = new client_1.PrismaClient(); +exports.default = prisma; +//# sourceMappingURL=prisma.js.map \ No newline at end of file diff --git a/mission 10/dist/lib/prisma.js.map b/mission 10/dist/lib/prisma.js.map new file mode 100644 index 000000000..538cc265d --- /dev/null +++ b/mission 10/dist/lib/prisma.js.map @@ -0,0 +1 @@ +{"version":3,"file":"prisma.js","sourceRoot":"","sources":["../../src/lib/prisma.ts"],"names":[],"mappings":";;AAAA,2CAA8C;AAE9C,MAAM,MAAM,GAAG,IAAI,qBAAY,EAAE,CAAC;AAElC,kBAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/lib/s3.js b/mission 10/dist/lib/s3.js new file mode 100644 index 000000000..0d2da6500 --- /dev/null +++ b/mission 10/dist/lib/s3.js @@ -0,0 +1,34 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.uploadS3 = void 0; +const client_s3_1 = require("@aws-sdk/client-s3"); +const multer_1 = __importDefault(require("multer")); +const multer_s3_1 = __importDefault(require("multer-s3")); +const uuid_1 = require("uuid"); +// AWS.config.update({ +// region: process.env.AWS_REGION, +// accessKeyId: process.env.AWS_ACCESS_KEY_ID, +// secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, +// }); +// const s3 = new AWS.S3({}); +exports.uploadS3 = (0, multer_1.default)({ + storage: (0, multer_s3_1.default)({ + s3: new client_s3_1.S3Client({ + credentials: { + accessKeyId: process.env.AWS_ACCESS_KEY_ID, + secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, + }, + region: process.env.AWS_REGION, + }), + bucket: process.env.AWS_S3_BUCKET, + contentType: multer_s3_1.default.AUTO_CONTENT_TYPE, + key: (req, file, cb) => { + const ext = file.originalname.split(".").pop(); + cb(null, `users/${(0, uuid_1.v4)()}.${ext}`); + }, + }), +}); +//# sourceMappingURL=s3.js.map \ No newline at end of file diff --git a/mission 10/dist/lib/s3.js.map b/mission 10/dist/lib/s3.js.map new file mode 100644 index 000000000..be4be691e --- /dev/null +++ b/mission 10/dist/lib/s3.js.map @@ -0,0 +1 @@ +{"version":3,"file":"s3.js","sourceRoot":"","sources":["../../src/lib/s3.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA8C;AAC9C,oDAA4B;AAC5B,0DAAiC;AACjC,+BAAkC;AAElC,sBAAsB;AACtB,oCAAoC;AACpC,gDAAgD;AAChD,wDAAwD;AACxD,MAAM;AAEN,6BAA6B;AAEhB,QAAA,QAAQ,GAAG,IAAA,gBAAM,EAAC;IAC7B,OAAO,EAAE,IAAA,mBAAQ,EAAC;QAChB,EAAE,EAAE,IAAI,oBAAQ,CAAC;YACf,WAAW,EAAE;gBACX,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,iBAA2B;gBACpD,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,qBAA+B;aAC7D;YACD,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU;SAC/B,CAAC;QACF,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,aAAc;QAClC,WAAW,EAAE,mBAAQ,CAAC,iBAAiB;QACvC,GAAG,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE;YACrB,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YAC/C,EAAE,CAAC,IAAI,EAAE,SAAS,IAAA,SAAI,GAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QACrC,CAAC;KACF,CAAC;CACH,CAAC,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/lib/token.js b/mission 10/dist/lib/token.js new file mode 100644 index 000000000..c1b56bb85 --- /dev/null +++ b/mission 10/dist/lib/token.js @@ -0,0 +1,28 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.generateTokens = generateTokens; +exports.verifyAccessToken = verifyAccessToken; +exports.verifyRefreshToken = verifyRefreshToken; +const jsonwebtoken_1 = __importDefault(require("jsonwebtoken")); +const constants_1 = require("./constants"); +function generateTokens(userId) { + const accessToken = jsonwebtoken_1.default.sign({ sub: userId }, constants_1.JWT_ACCESS_TOKEN_SECRET, { + expiresIn: '1h', + }); + const refreshToken = jsonwebtoken_1.default.sign({ sub: userId }, constants_1.JWT_REFRESH_TOKEN_SECRET, { + expiresIn: '1d', + }); + return { accessToken, refreshToken }; +} +function verifyAccessToken(token) { + const decoded = jsonwebtoken_1.default.verify(token, constants_1.JWT_ACCESS_TOKEN_SECRET); + return { userId: decoded.sub }; +} +function verifyRefreshToken(token) { + const decoded = jsonwebtoken_1.default.verify(token, constants_1.JWT_REFRESH_TOKEN_SECRET); + return { userId: decoded.sub }; +} +//# sourceMappingURL=token.js.map \ No newline at end of file diff --git a/mission 10/dist/lib/token.js.map b/mission 10/dist/lib/token.js.map new file mode 100644 index 000000000..44f5bfc99 --- /dev/null +++ b/mission 10/dist/lib/token.js.map @@ -0,0 +1 @@ +{"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/lib/token.ts"],"names":[],"mappings":";;;;;AA0BS,wCAAc;AAAE,8CAAiB;AAAE,gDAAkB;AA1B7D,gEAA+B;AAChC,2CAGqB;AAErB,SAAS,cAAc,CAAC,MAAc;IACpC,MAAM,WAAW,GAAG,sBAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,mCAAuB,EAAE;QACrE,SAAS,EAAE,IAAI;KAChB,CAAC,CAAC;IACH,MAAM,YAAY,GAAG,sBAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,oCAAwB,EAAE;QACvE,SAAS,EAAE,IAAI;KAChB,CAAC,CAAC;IACH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;AACvC,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa;IACtC,MAAM,OAAO,GAAG,sBAAG,CAAC,MAAM,CAAC,KAAK,EAAE,mCAAuB,CAAC,CAAC;IAC3D,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;AACjC,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa;IACvC,MAAM,OAAO,GAAG,sBAAG,CAAC,MAAM,CAAC,KAAK,EAAE,oCAAwB,CAAC,CAAC;IAC5D,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;AACjC,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/middlewares/errorHandler.js b/mission 10/dist/middlewares/errorHandler.js new file mode 100644 index 000000000..322d71c43 --- /dev/null +++ b/mission 10/dist/middlewares/errorHandler.js @@ -0,0 +1,21 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.errorHandler = errorHandler; +const zod_1 = require("zod"); +const http_status_1 = __importDefault(require("http-status")); +function errorHandler(err, req, res, next) { + if (err instanceof zod_1.z.ZodError) { + return res.status(http_status_1.default.BAD_REQUEST).json({ error: err.issues }); + } + if (err.code === "P2025") { + return res.status(http_status_1.default.NOT_FOUND).json({ error: "Record not found" }); + } + console.error("unhandled Error:", err); + return res + .status(http_status_1.default.INTERNAL_SERVER_ERROR) + .json({ error: "Internal Server Error" }); +} +//# sourceMappingURL=errorHandler.js.map \ No newline at end of file diff --git a/mission 10/dist/middlewares/errorHandler.js.map b/mission 10/dist/middlewares/errorHandler.js.map new file mode 100644 index 000000000..b256aadf9 --- /dev/null +++ b/mission 10/dist/middlewares/errorHandler.js.map @@ -0,0 +1 @@ +{"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../src/middlewares/errorHandler.ts"],"names":[],"mappings":";;;;;AAQA,oCAaC;AArBD,6BAAwB;AACxB,8DAAqC;AAOrC,SAAgB,YAAY,CAAC,GAAkB,EAAE,GAAY,EAAE,GAAa,EAAE,IAAkB;IAC9F,IAAI,GAAG,YAAY,OAAC,CAAC,QAAQ,EAAE,CAAC;QAC9B,OAAO,GAAG,CAAC,MAAM,CAAC,qBAAU,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO,GAAG,CAAC,MAAM,CAAC,qBAAU,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;IACvC,OAAO,GAAG;SACP,MAAM,CAAC,qBAAU,CAAC,qBAAqB,CAAC;SACxC,IAAI,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,CAAC;AAC9C,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/repositories/alertRepository.js b/mission 10/dist/repositories/alertRepository.js new file mode 100644 index 000000000..c3bd394c9 --- /dev/null +++ b/mission 10/dist/repositories/alertRepository.js @@ -0,0 +1,36 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.AlertRepository = void 0; +const prisma_1 = __importDefault(require("../lib/prisma")); +class AlertRepository { + async createAlert(data) { + return prisma_1.default.alert.create({ data }); + } + async findByUserId(userId) { + return prisma_1.default.alert.findMany({ + where: { userId }, + orderBy: { createdAt: "desc" }, + }); + } + async markAsRead(id) { + return prisma_1.default.alert.update({ + where: { id }, + data: { isRead: true }, + }); + } + async countUnread(userId) { + return prisma_1.default.alert.count({ + where: { userId, isRead: false }, + }); + } + async findById(id) { + return prisma_1.default.alert.findUnique({ + where: { id }, + }); + } +} +exports.AlertRepository = AlertRepository; +//# sourceMappingURL=alertRepository.js.map \ No newline at end of file diff --git a/mission 10/dist/repositories/alertRepository.js.map b/mission 10/dist/repositories/alertRepository.js.map new file mode 100644 index 000000000..f425f1a4c --- /dev/null +++ b/mission 10/dist/repositories/alertRepository.js.map @@ -0,0 +1 @@ +{"version":3,"file":"alertRepository.js","sourceRoot":"","sources":["../../src/repositories/alertRepository.ts"],"names":[],"mappings":";;;;;;AAAA,2DAAmC;AAEnC,MAAa,eAAe;IAC1B,KAAK,CAAC,WAAW,CAAC,IAAwD;QACxE,OAAO,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAAc;QAC/B,OAAO,gBAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;YAC3B,KAAK,EAAE,EAAE,MAAM,EAAE;YACjB,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE;SAC/B,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAU;QACzB,OAAO,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC;YACzB,KAAK,EAAE,EAAE,EAAE,EAAE;YACb,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;SACvB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAc;QAC9B,OAAO,gBAAM,CAAC,KAAK,CAAC,KAAK,CAAC;YACxB,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;SACjC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,EAAU;QACvB,OAAO,gBAAM,CAAC,KAAK,CAAC,UAAU,CAAC;YAC7B,KAAK,EAAE,EAAE,EAAE,EAAE;SACd,CAAC,CAAC;IACL,CAAC;CACF;AA9BD,0CA8BC"} \ No newline at end of file diff --git a/mission 10/dist/repositories/articleRepository.js b/mission 10/dist/repositories/articleRepository.js new file mode 100644 index 000000000..749da6c63 --- /dev/null +++ b/mission 10/dist/repositories/articleRepository.js @@ -0,0 +1,41 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ArticleRepository = void 0; +const prisma_1 = __importDefault(require("../lib/prisma")); +class ArticleRepository { + async createArticle(data) { + return prisma_1.default.article.create({ data }); + } + async findMany(where, skip, take) { + return prisma_1.default.article.findMany({ + skip, + take, + orderBy: { createdAt: "desc" }, + select: { id: true, title: true, content: true, createdAt: true }, + where, + }); + } + async findById(id) { + return prisma_1.default.article.findUnique({ + where: { id }, + select: { id: true, userId: true, title: true, content: true, createdAt: true }, + }); + } + async updatedArticle(id, data) { + const updateData = {}; + if (data.title !== undefined) + updateData.title = data.title; + if (data.content !== undefined) + updateData.content = data.content; + return prisma_1.default.article.update({ where: { id }, data: updateData }); + } + async deleteArticle(id) { + await prisma_1.default.article.delete({ where: { id } }); + } +} +exports.ArticleRepository = ArticleRepository; +exports.default = new ArticleRepository(); +//# sourceMappingURL=articleRepository.js.map \ No newline at end of file diff --git a/mission 10/dist/repositories/articleRepository.js.map b/mission 10/dist/repositories/articleRepository.js.map new file mode 100644 index 000000000..09314d7b9 --- /dev/null +++ b/mission 10/dist/repositories/articleRepository.js.map @@ -0,0 +1 @@ +{"version":3,"file":"articleRepository.js","sourceRoot":"","sources":["../../src/repositories/articleRepository.ts"],"names":[],"mappings":";;;;;;AAAA,2DAAmC;AAGnC,MAAa,iBAAiB;IAC5B,KAAK,CAAC,aAAa,CAAC,IAAwD;QAC1E,OAAO,gBAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAA+B,EAAE,IAAY,EAAE,IAAY;QACxE,OAAO,gBAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;YAC7B,IAAI;YACJ,IAAI;YACJ,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE;YAC9B,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;YACjE,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,EAAU;QACvB,OAAO,gBAAM,CAAC,OAAO,CAAC,UAAU,CAAC;YAC/B,KAAK,EAAE,EAAE,EAAE,EAAE;YACb,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;SAChF,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,EAAU,EAAE,IAA0C;QACzE,MAAM,UAAU,GAAyC,EAAE,CAAC;QAC5D,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,UAAU,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QAC5D,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;YAAE,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAElE,OAAO,gBAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,EAAU;QAC5B,MAAM,gBAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACjD,CAAC;CACF;AAjCD,8CAiCC;AAED,kBAAe,IAAI,iBAAiB,EAAE,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/repositories/commentRepository.js b/mission 10/dist/repositories/commentRepository.js new file mode 100644 index 000000000..30156d793 --- /dev/null +++ b/mission 10/dist/repositories/commentRepository.js @@ -0,0 +1,52 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CommentRepository = void 0; +const prisma_1 = __importDefault(require("../lib/prisma")); +class CommentRepository { + async createProductComment(userId, productId, content) { + return prisma_1.default.comment.create({ + data: { content, productId, articleId: null, userId }, + }); + } + async createArticleComment(userId, articleId, content) { + return prisma_1.default.comment.create({ + data: { content, productId: null, articleId, userId }, + }); + } + async findById(commentId) { + return prisma_1.default.comment.findUnique({ where: { id: commentId } }); + } + async updateComment(commentId, content) { + return prisma_1.default.comment.update({ + where: { id: commentId }, + data: { content }, + }); + } + async deleteComment(commentId) { + return prisma_1.default.comment.delete({ where: { id: commentId } }); + } + async findProductComments(productId, lastId) { + return prisma_1.default.comment.findMany({ + where: { articleId: null, productId }, + take: 5, + skip: lastId ? 1 : 0, + ...(lastId && { cursor: { id: lastId } }), + select: { id: true, content: true, createdAt: true }, + }); + } + async findArticleComments(articleId, lastId) { + return prisma_1.default.comment.findMany({ + where: { articleId, productId: null }, + take: 5, + skip: lastId ? 1 : 0, + ...(lastId && { cursor: { id: lastId } }), + select: { id: true, content: true, createdAt: true }, + }); + } +} +exports.CommentRepository = CommentRepository; +exports.default = new CommentRepository(); +//# sourceMappingURL=commentRepository.js.map \ No newline at end of file diff --git a/mission 10/dist/repositories/commentRepository.js.map b/mission 10/dist/repositories/commentRepository.js.map new file mode 100644 index 000000000..4153947d7 --- /dev/null +++ b/mission 10/dist/repositories/commentRepository.js.map @@ -0,0 +1 @@ +{"version":3,"file":"commentRepository.js","sourceRoot":"","sources":["../../src/repositories/commentRepository.ts"],"names":[],"mappings":";;;;;;AAAA,2DAAmC;AAEnC,MAAa,iBAAiB;IAC5B,KAAK,CAAC,oBAAoB,CAAC,MAAc,EAAE,SAAiB,EAAE,OAAe;QAC3E,OAAO,gBAAM,CAAC,OAAO,CAAC,MAAM,CAAC;YAC3B,IAAI,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE;SACtD,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,MAAc,EAAE,SAAiB,EAAE,OAAe;QAC3E,OAAO,gBAAM,CAAC,OAAO,CAAC,MAAM,CAAC;YAC3B,IAAI,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE;SACtD,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,SAAiB;QAC9B,OAAO,gBAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,SAAiB,EAAE,OAAe;QACpD,OAAO,gBAAM,CAAC,OAAO,CAAC,MAAM,CAAC;YAC3B,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE;YACxB,IAAI,EAAE,EAAE,OAAO,EAAE;SAClB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,SAAiB;QACnC,OAAO,gBAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,SAAiB,EAAE,MAAe;QAC1D,OAAO,gBAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;YAC7B,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;YACrC,IAAI,EAAE,CAAC;YACP,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACpB,GAAG,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC;YACzC,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;SACrD,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,SAAiB,EAAE,MAAe;QAC1D,OAAO,gBAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;YAC7B,KAAK,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE;YACrC,IAAI,EAAE,CAAC;YACP,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACpB,GAAG,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC;YACzC,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;SACrD,CAAC,CAAC;IACL,CAAC;CACF;AA/CD,8CA+CC;AAED,kBAAe,IAAI,iBAAiB,EAAE,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/repositories/likeRepository.js b/mission 10/dist/repositories/likeRepository.js new file mode 100644 index 000000000..1771adb2c --- /dev/null +++ b/mission 10/dist/repositories/likeRepository.js @@ -0,0 +1,82 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LikeRepository = void 0; +const prisma_1 = __importDefault(require("../lib/prisma")); +class LikeRepository { + async findArticle(articleId) { + return prisma_1.default.article.findUnique({ where: { id: articleId } }); + } + async findProduct(productId) { + return prisma_1.default.product.findUnique({ where: { id: productId } }); + } + async findArticleLike(userId, articleId) { + return prisma_1.default.like.findUnique({ + where: { userId_articleId: { userId, articleId } }, + }); + } + async findProductLike(userId, productId) { + return prisma_1.default.like.findUnique({ + where: { userId_productId: { userId, productId } }, + }); + } + async toggleArticleLike(userId, articleId, current) { + return prisma_1.default.like.update({ + where: { userId_articleId: { userId, articleId } }, + data: { like: !current }, + }); + } + async toggleProductLike(userId, productId, current) { + return prisma_1.default.like.update({ + where: { userId_productId: { userId, productId } }, + data: { like: !current }, + }); + } + async createArticleLike(userId, articleId) { + return prisma_1.default.like.create({ + data: { like: true, userId, articleId }, + }); + } + async createProductLike(userId, productId) { + return prisma_1.default.like.create({ + data: { like: true, userId, productId }, + }); + } + async findLikedArticles(userId) { + return prisma_1.default.like.findMany({ + where: { userId, articleId: { not: null }, like: true }, + include: { + article: { select: { id: true, title: true } }, + }, + }); + } + async findLikedProducts(userId) { + return prisma_1.default.like.findMany({ + where: { userId, productId: { not: null }, like: true }, + include: { + product: { select: { id: true, name: true, price: true, tags: true } }, + }, + }); + } + async findUsersWhoLikedProduct(productId) { + const likes = await prisma_1.default.like.findMany({ + where: { + productId, + like: true, + }, + select: { + user: { + select: { + id: true, + nickname: true, + }, + }, + }, + }); + return likes.map((like) => like.user); + } +} +exports.LikeRepository = LikeRepository; +//# sourceMappingURL=likeRepository.js.map \ No newline at end of file diff --git a/mission 10/dist/repositories/likeRepository.js.map b/mission 10/dist/repositories/likeRepository.js.map new file mode 100644 index 000000000..587086b15 --- /dev/null +++ b/mission 10/dist/repositories/likeRepository.js.map @@ -0,0 +1 @@ +{"version":3,"file":"likeRepository.js","sourceRoot":"","sources":["../../src/repositories/likeRepository.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/mission 10/dist/repositories/productRepository.js b/mission 10/dist/repositories/productRepository.js new file mode 100644 index 000000000..433c31ae0 --- /dev/null +++ b/mission 10/dist/repositories/productRepository.js @@ -0,0 +1,50 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ProductRepository = void 0; +const prisma_1 = __importDefault(require("../lib/prisma")); +class ProductRepository { + async createProduct(data) { + return prisma_1.default.product.create({ data }); + } + async findMany(where, skip, take) { + return prisma_1.default.product.findMany({ + skip, + take, + orderBy: { createdAt: "desc" }, + select: { + id: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + where, + }); + } + async findById(id) { + return prisma_1.default.product.findUnique({ + where: { id }, + select: { + id: true, + userId: true, + name: true, + description: true, + price: true, + tags: true, + createdAt: true, + }, + }); + } + async updateProduct(id, data) { + return prisma_1.default.product.update({ where: { id }, data }); + } + async deleteProduct(id) { + return prisma_1.default.product.delete({ where: { id } }); + } +} +exports.ProductRepository = ProductRepository; +//# sourceMappingURL=productRepository.js.map \ No newline at end of file diff --git a/mission 10/dist/repositories/productRepository.js.map b/mission 10/dist/repositories/productRepository.js.map new file mode 100644 index 000000000..cc4fa03e6 --- /dev/null +++ b/mission 10/dist/repositories/productRepository.js.map @@ -0,0 +1 @@ +{"version":3,"file":"productRepository.js","sourceRoot":"","sources":["../../src/repositories/productRepository.ts"],"names":[],"mappings":";;;;;;AAAA,2DAAmC;AAInC,MAAa,iBAAiB;IAC5B,KAAK,CAAC,aAAa,CAAC,IAAwF;QAC1G,OAAO,gBAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAA+B,EAAE,IAAY,EAAE,IAAY;QACxE,OAAO,gBAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;YAC7B,IAAI;YACJ,IAAI;YACJ,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE;YAC9B,MAAM,EAAE;gBACN,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,IAAI;gBACV,WAAW,EAAE,IAAI;gBACjB,KAAK,EAAE,IAAI;gBACX,IAAI,EAAE,IAAI;gBACV,SAAS,EAAE,IAAI;aAChB;YACD,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,EAAU;QACvB,OAAO,gBAAM,CAAC,OAAO,CAAC,UAAU,CAAC;YAC/B,KAAK,EAAE,EAAE,EAAE,EAAE;YACb,MAAM,EAAE;gBACN,EAAE,EAAE,IAAI;gBACR,MAAM,EAAE,IAAI;gBACZ,IAAI,EAAE,IAAI;gBACV,WAAW,EAAE,IAAI;gBACjB,KAAK,EAAE,IAAI;gBACX,IAAI,EAAE,IAAI;gBACV,SAAS,EAAE,IAAI;aAChB;SACF,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,EAAU,EAAE,IAAiF;QAC/G,OAAO,gBAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,EAAU;QAC5B,OAAO,gBAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAClD,CAAC;CACF;AA5CD,8CA4CC"} \ No newline at end of file diff --git a/mission 10/dist/repositories/userRepository.js b/mission 10/dist/repositories/userRepository.js new file mode 100644 index 000000000..8973d69d2 --- /dev/null +++ b/mission 10/dist/repositories/userRepository.js @@ -0,0 +1,32 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UserRepository = void 0; +const prisma_1 = __importDefault(require("../lib/prisma")); +class UserRepository { + async findByEmail(email) { + return prisma_1.default.user.findUnique({ where: { email } }); + } + async findById(id) { + return prisma_1.default.user.findUnique({ + where: { id }, + select: { id: true, email: true, nickname: true, image: true, createdAt: true, updatedAt: true }, + }); + } + async createUser(email, nickname, password) { + return prisma_1.default.user.create({ data: { email, nickname, password } }); + } + async updateUser(id, data) { + return prisma_1.default.user.update({ where: { id }, data }); + } + async findProductsByUserId(userId) { + return prisma_1.default.product.findMany({ + where: { userId }, + select: { name: true, description: true, price: true, tags: true }, + }); + } +} +exports.UserRepository = UserRepository; +//# sourceMappingURL=userRepository.js.map \ No newline at end of file diff --git a/mission 10/dist/repositories/userRepository.js.map b/mission 10/dist/repositories/userRepository.js.map new file mode 100644 index 000000000..56c5f802d --- /dev/null +++ b/mission 10/dist/repositories/userRepository.js.map @@ -0,0 +1 @@ +{"version":3,"file":"userRepository.js","sourceRoot":"","sources":["../../src/repositories/userRepository.ts"],"names":[],"mappings":";;;;;;AAAA,2DAAmC;AAEnC,MAAa,cAAc;IACzB,KAAK,CAAC,WAAW,CAAC,KAAa;QAC7B,OAAO,gBAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,EAAU;QACvB,OAAO,gBAAM,CAAC,IAAI,CAAC,UAAU,CAAC;YAC5B,KAAK,EAAE,EAAE,EAAE,EAAE;YACb,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;SACjG,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,KAAa,EAAE,QAAgB,EAAE,QAAgB;QAChE,OAAO,gBAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAU,EAAE,IAAoE;QAC/F,OAAO,gBAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,MAAc;QACvC,OAAO,gBAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;YAC7B,KAAK,EAAE,EAAE,MAAM,EAAE;YACjB,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;SACnE,CAAC,CAAC;IACL,CAAC;CACF;AA1BD,wCA0BC"} \ No newline at end of file diff --git a/mission 10/dist/routers/alertRouter.js b/mission 10/dist/routers/alertRouter.js new file mode 100644 index 000000000..6c681432e --- /dev/null +++ b/mission 10/dist/routers/alertRouter.js @@ -0,0 +1,14 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const express_1 = __importDefault(require("express")); +const passport_1 = __importDefault(require("../lib/passport")); +const alertController_1 = require("../controllers/alertController"); +const router = express_1.default.Router(); +const controller = new alertController_1.AlertController(); +router.get("/", passport_1.default.authenticate("access-token", { session: false }), controller.list); +router.patch("/:id/read", passport_1.default.authenticate("access-token", { session: false }), controller.markAsRead); +exports.default = router; +//# sourceMappingURL=alertRouter.js.map \ No newline at end of file diff --git a/mission 10/dist/routers/alertRouter.js.map b/mission 10/dist/routers/alertRouter.js.map new file mode 100644 index 000000000..971cc7f92 --- /dev/null +++ b/mission 10/dist/routers/alertRouter.js.map @@ -0,0 +1 @@ +{"version":3,"file":"alertRouter.js","sourceRoot":"","sources":["../../src/routers/alertRouter.ts"],"names":[],"mappings":";;;;;AAAA,sDAA8B;AAC9B,+DAAuC;AACvC,oEAAiE;AAEjE,MAAM,MAAM,GAAG,iBAAO,CAAC,MAAM,EAAE,CAAC;AAChC,MAAM,UAAU,GAAG,IAAI,iCAAe,EAAE,CAAC;AAEzC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;AAE5F,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;AAE5G,kBAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/routers/articleRouter.js b/mission 10/dist/routers/articleRouter.js new file mode 100644 index 000000000..be57e1523 --- /dev/null +++ b/mission 10/dist/routers/articleRouter.js @@ -0,0 +1,17 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const express_1 = __importDefault(require("express")); +const passport_1 = __importDefault(require("../lib/passport")); +const articleController_1 = require("../controllers/articleController"); +const router = express_1.default.Router(); +const controller = new articleController_1.ArticleController(); +router.post("/", passport_1.default.authenticate("access-token", { session: false }), controller.create); +router.patch("/:id", passport_1.default.authenticate("access-token", { session: false }), controller.update); +router.delete("/:id", passport_1.default.authenticate("access-token", { session: false }), controller.delete); +router.get("/", controller.list); +router.get("/:id", controller.detail); +exports.default = router; +//# sourceMappingURL=articleRouter.js.map \ No newline at end of file diff --git a/mission 10/dist/routers/articleRouter.js.map b/mission 10/dist/routers/articleRouter.js.map new file mode 100644 index 000000000..dec555b30 --- /dev/null +++ b/mission 10/dist/routers/articleRouter.js.map @@ -0,0 +1 @@ +{"version":3,"file":"articleRouter.js","sourceRoot":"","sources":["../../src/routers/articleRouter.ts"],"names":[],"mappings":";;;;;AAAA,sDAA8B;AAC9B,+DAAuC;AACvC,wEAAqE;AAErE,MAAM,MAAM,GAAG,iBAAO,CAAC,MAAM,EAAE,CAAC;AAChC,MAAM,UAAU,GAAG,IAAI,qCAAiB,EAAE,CAAC;AAE3C,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;AAC/F,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;AACnG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;AAEpG,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;AACjC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;AAEtC,kBAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/routers/commentRouter.js b/mission 10/dist/routers/commentRouter.js new file mode 100644 index 000000000..1008a3791 --- /dev/null +++ b/mission 10/dist/routers/commentRouter.js @@ -0,0 +1,18 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const express_1 = __importDefault(require("express")); +const passport_1 = __importDefault(require("../lib/passport")); +const commentController_1 = require("../controllers/commentController"); +const router = express_1.default.Router(); +const controller = new commentController_1.CommentController(); +router.post("/products/:id", passport_1.default.authenticate("access-token", { session: false }), controller.createProductComment); +router.post("/articles/:id", passport_1.default.authenticate("access-token", { session: false }), controller.createArticleComment); +router.patch("/:id", passport_1.default.authenticate("access-token", { session: false }), controller.modifyComment); +router.delete("/:id", passport_1.default.authenticate("access-token", { session: false }), controller.deleteComment); +router.get("/products/:id", controller.productCommentList); +router.get("/articles/:id", controller.articleCommentList); +exports.default = router; +//# sourceMappingURL=commentRouter.js.map \ No newline at end of file diff --git a/mission 10/dist/routers/commentRouter.js.map b/mission 10/dist/routers/commentRouter.js.map new file mode 100644 index 000000000..74322116b --- /dev/null +++ b/mission 10/dist/routers/commentRouter.js.map @@ -0,0 +1 @@ +{"version":3,"file":"commentRouter.js","sourceRoot":"","sources":["../../src/routers/commentRouter.ts"],"names":[],"mappings":";;;;;AAAA,sDAA8B;AAC9B,+DAAuC;AACvC,wEAAqE;AAErE,MAAM,MAAM,GAAG,iBAAO,CAAC,MAAM,EAAE,CAAC;AAChC,MAAM,UAAU,GAAG,IAAI,qCAAiB,EAAE,CAAC;AAE3C,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAC;AACzH,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAC;AACzH,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,aAAa,CAAC,CAAC;AAC1G,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,aAAa,CAAC,CAAC;AAE3G,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,kBAAkB,CAAC,CAAC;AAC3D,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,kBAAkB,CAAC,CAAC;AAE3D,kBAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/routers/index.js b/mission 10/dist/routers/index.js new file mode 100644 index 000000000..f7b1efbba --- /dev/null +++ b/mission 10/dist/routers/index.js @@ -0,0 +1,23 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const express_1 = __importDefault(require("express")); +const userRouter_1 = __importDefault(require("./userRouter")); +const articleRouter_1 = __importDefault(require("./articleRouter")); +const productRouter_1 = __importDefault(require("./productRouter")); +const commentRouter_1 = __importDefault(require("./commentRouter")); +const likeRouter_1 = __importDefault(require("./likeRouter")); +const photoRouter_1 = __importDefault(require("./photoRouter")); +const alertRouter_1 = __importDefault(require("./alertRouter")); +const router = express_1.default.Router(); +router.use("/users", userRouter_1.default); +router.use("/articles", articleRouter_1.default); +router.use("/products", productRouter_1.default); +router.use("/comments", commentRouter_1.default); +router.use("/likes", likeRouter_1.default); +router.use(photoRouter_1.default); +router.use("/alerts", alertRouter_1.default); +exports.default = router; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/mission 10/dist/routers/index.js.map b/mission 10/dist/routers/index.js.map new file mode 100644 index 000000000..69c509901 --- /dev/null +++ b/mission 10/dist/routers/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/routers/index.ts"],"names":[],"mappings":";;;;;AAAA,sDAA8B;AAE9B,8DAAsC;AACtC,oEAA4C;AAC5C,oEAA4C;AAC5C,oEAA4C;AAC5C,8DAAsC;AACtC,gEAAwC;AACxC,gEAAwC;AAExC,MAAM,MAAM,GAAG,iBAAO,CAAC,MAAM,EAAE,CAAC;AAEhC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,oBAAU,CAAC,CAAC;AACjC,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,uBAAa,CAAC,CAAC;AACvC,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,uBAAa,CAAC,CAAC;AACvC,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,uBAAa,CAAC,CAAC;AACvC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,oBAAU,CAAC,CAAC;AACjC,MAAM,CAAC,GAAG,CAAC,qBAAW,CAAC,CAAC;AACxB,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,qBAAW,CAAC,CAAC;AAEnC,kBAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/routers/likeRouter.js b/mission 10/dist/routers/likeRouter.js new file mode 100644 index 000000000..11f56f690 --- /dev/null +++ b/mission 10/dist/routers/likeRouter.js @@ -0,0 +1,16 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const express_1 = __importDefault(require("express")); +const passport_1 = __importDefault(require("../lib/passport")); +const likeController_1 = require("../controllers/likeController"); +const router = express_1.default.Router(); +const controller = new likeController_1.LikeController(); +router.post("/articles/:id", passport_1.default.authenticate("access-token", { session: false }), controller.likeArticle); +router.post("/products/:id", passport_1.default.authenticate("access-token", { session: false }), controller.likeProduct); +router.get("/articles", passport_1.default.authenticate("access-token", { session: false }), controller.getLikedArticles); +router.get("/products", passport_1.default.authenticate("access-token", { session: false }), controller.getLikedProducts); +exports.default = router; +//# sourceMappingURL=likeRouter.js.map \ No newline at end of file diff --git a/mission 10/dist/routers/likeRouter.js.map b/mission 10/dist/routers/likeRouter.js.map new file mode 100644 index 000000000..b7f620abd --- /dev/null +++ b/mission 10/dist/routers/likeRouter.js.map @@ -0,0 +1 @@ +{"version":3,"file":"likeRouter.js","sourceRoot":"","sources":["../../src/routers/likeRouter.ts"],"names":[],"mappings":";;;;;AAAA,sDAA8B;AAC9B,+DAAuC;AACvC,kEAA+D;AAE/D,MAAM,MAAM,GAAG,iBAAO,CAAC,MAAM,EAAE,CAAC;AAChC,MAAM,UAAU,GAAG,IAAI,+BAAc,EAAE,CAAC;AAExC,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;AAChH,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;AAChH,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,gBAAgB,CAAC,CAAC;AAChH,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,gBAAgB,CAAC,CAAC;AAEhH,kBAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/routers/photoRouter.js b/mission 10/dist/routers/photoRouter.js new file mode 100644 index 000000000..cf0c90a3d --- /dev/null +++ b/mission 10/dist/routers/photoRouter.js @@ -0,0 +1,14 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const express_1 = __importDefault(require("express")); +const passport_1 = __importDefault(require("../lib/passport")); +const photoController_1 = require("../controllers/photoController"); +const s3_1 = require("../lib/s3"); +const router = express_1.default.Router(); +const controller = new photoController_1.PhotoController(); +router.post("/", passport_1.default.authenticate("access-token", { session: false }), s3_1.uploadS3.single("image"), controller.upload); +exports.default = router; +//# sourceMappingURL=photoRouter.js.map \ No newline at end of file diff --git a/mission 10/dist/routers/photoRouter.js.map b/mission 10/dist/routers/photoRouter.js.map new file mode 100644 index 000000000..c55f13b5c --- /dev/null +++ b/mission 10/dist/routers/photoRouter.js.map @@ -0,0 +1 @@ +{"version":3,"file":"photoRouter.js","sourceRoot":"","sources":["../../src/routers/photoRouter.ts"],"names":[],"mappings":";;;;;AAAA,sDAA8B;AAC9B,+DAAuC;AACvC,oEAAiE;AACjE,kCAAoC;AAEpC,MAAM,MAAM,GAAG,iBAAO,CAAC,MAAM,EAAE,CAAC;AAChC,MAAM,UAAU,GAAG,IAAI,iCAAe,EAAE,CAAC;AAEzC,MAAM,CAAC,IAAI,CACT,GAAG,EACH,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EACzD,aAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EACxB,UAAU,CAAC,MAAM,CAClB,CAAC;AAEF,kBAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/routers/productRouter.js b/mission 10/dist/routers/productRouter.js new file mode 100644 index 000000000..c26e93ed6 --- /dev/null +++ b/mission 10/dist/routers/productRouter.js @@ -0,0 +1,19 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const express_1 = __importDefault(require("express")); +const passport_1 = __importDefault(require("../lib/passport")); +const productController_1 = require("../controllers/productController"); +const router = express_1.default.Router(); +const controller = new productController_1.ProductController(); +// ✅ 인증 필요 +router.post("/", passport_1.default.authenticate("access-token", { session: false }), controller.create); +router.patch("/:id", passport_1.default.authenticate("access-token", { session: false }), controller.update); +router.delete("/:id", passport_1.default.authenticate("access-token", { session: false }), controller.delete); +// ✅ 인증 필요 X (공개) +router.get("/", controller.list); +router.get("/:id", controller.detail); +exports.default = router; +//# sourceMappingURL=productRouter.js.map \ No newline at end of file diff --git a/mission 10/dist/routers/productRouter.js.map b/mission 10/dist/routers/productRouter.js.map new file mode 100644 index 000000000..f532d7656 --- /dev/null +++ b/mission 10/dist/routers/productRouter.js.map @@ -0,0 +1 @@ +{"version":3,"file":"productRouter.js","sourceRoot":"","sources":["../../src/routers/productRouter.ts"],"names":[],"mappings":";;;;;AAAA,sDAA8B;AAC9B,+DAAuC;AACvC,wEAAqE;AAErE,MAAM,MAAM,GAAG,iBAAO,CAAC,MAAM,EAAE,CAAC;AAChC,MAAM,UAAU,GAAG,IAAI,qCAAiB,EAAE,CAAC;AAE3C,UAAU;AACV,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;AAC/F,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;AACnG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;AAEpG,iBAAiB;AACjB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;AACjC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;AAEtC,kBAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/routers/userRouter.js b/mission 10/dist/routers/userRouter.js new file mode 100644 index 000000000..4cac97a05 --- /dev/null +++ b/mission 10/dist/routers/userRouter.js @@ -0,0 +1,32 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const express_1 = __importDefault(require("express")); +const passport_1 = __importDefault(require("../lib/passport")); +const userController_1 = require("../controllers/userController"); +const router = express_1.default.Router(); +const controller = new userController_1.UserController(); +router.post("/register", controller.register); +router.post("/login", (req, res, next) => { + passport_1.default.authenticate("local", { session: false }, (err, user, info) => { + if (err) + return next(err); + if (!user) { + return res.status(401).json({ + message: "Unauthorized", + }); + } + req.user = user; + next(); + })(req, res, next); +}, controller.login); +router.get("/profile", passport_1.default.authenticate("access-token", { session: false }), controller.profile); +router.patch("/modifyInformation", passport_1.default.authenticate("access-token", { session: false }), controller.modifyInformation); +router.patch("/modifyPassword", passport_1.default.authenticate("access-token", { session: false }), controller.modifyPassword); +router.get("/products", passport_1.default.authenticate("access-token", { session: false }), controller.products); +router.post("/refresh", passport_1.default.authenticate("refresh-token", { session: false }), controller.refreshTokens); +router.post("/logout", controller.logout); +exports.default = router; +//# sourceMappingURL=userRouter.js.map \ No newline at end of file diff --git a/mission 10/dist/routers/userRouter.js.map b/mission 10/dist/routers/userRouter.js.map new file mode 100644 index 000000000..e5b5437dc --- /dev/null +++ b/mission 10/dist/routers/userRouter.js.map @@ -0,0 +1 @@ +{"version":3,"file":"userRouter.js","sourceRoot":"","sources":["../../src/routers/userRouter.ts"],"names":[],"mappings":";;;;;AAAA,sDAA8B;AAC9B,+DAAuC;AACvC,kEAA+D;AAE/D,MAAM,MAAM,GAAG,iBAAO,CAAC,MAAM,EAAE,CAAC;AAChC,MAAM,UAAU,GAAG,IAAI,+BAAc,EAAE,CAAC;AAExC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;AAC9C,MAAM,CAAC,IAAI,CACT,QAAQ,EACR,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACjB,kBAAQ,CAAC,YAAY,CACnB,OAAO,EACP,EAAE,OAAO,EAAE,KAAK,EAAE,EAClB,CACE,GAAQ,EACR,IAA0B,EAC1B,IAAsC,EACtC,EAAE;QACF,IAAI,GAAG;YAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QAE1B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBAC1B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;QACL,CAAC;QAED,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;QAChB,IAAI,EAAE,CAAC;IACT,CAAC,CACF,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;AACpB,CAAC,EACD,UAAU,CAAC,KAAK,CACjB,CAAC;AAEF,MAAM,CAAC,GAAG,CACR,UAAU,EACV,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EACzD,UAAU,CAAC,OAAO,CACnB,CAAC;AACF,MAAM,CAAC,KAAK,CACV,oBAAoB,EACpB,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EACzD,UAAU,CAAC,iBAAiB,CAC7B,CAAC;AACF,MAAM,CAAC,KAAK,CACV,iBAAiB,EACjB,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EACzD,UAAU,CAAC,cAAc,CAC1B,CAAC;AACF,MAAM,CAAC,GAAG,CACR,WAAW,EACX,kBAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EACzD,UAAU,CAAC,QAAQ,CACpB,CAAC;AACF,MAAM,CAAC,IAAI,CACT,UAAU,EACV,kBAAQ,CAAC,YAAY,CAAC,eAAe,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAC1D,UAAU,CAAC,aAAa,CACzB,CAAC;AACF,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;AAE1C,kBAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/server.js b/mission 10/dist/server.js new file mode 100644 index 000000000..ecd558b02 --- /dev/null +++ b/mission 10/dist/server.js @@ -0,0 +1,8 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const app_1 = require("./app"); +const constants_1 = require("./lib/constants"); +app_1.server.listen(constants_1.PORT, () => { + console.log(`Server is running on http://localhost:${constants_1.PORT}`); +}); +//# sourceMappingURL=server.js.map \ No newline at end of file diff --git a/mission 10/dist/server.js.map b/mission 10/dist/server.js.map new file mode 100644 index 000000000..ddf1d474b --- /dev/null +++ b/mission 10/dist/server.js.map @@ -0,0 +1 @@ +{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";;AAAA,+BAAoC;AACpC,+CAAuC;AAEvC,YAAM,CAAC,MAAM,CAAC,gBAAI,EAAE,GAAG,EAAE;IACvB,OAAO,CAAC,GAAG,CAAC,yCAAyC,gBAAI,EAAE,CAAC,CAAC;AAC/D,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/services/alertService.js b/mission 10/dist/services/alertService.js new file mode 100644 index 000000000..f5be9b2af --- /dev/null +++ b/mission 10/dist/services/alertService.js @@ -0,0 +1,34 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.AlertService = void 0; +const alertRepository_1 = require("../repositories/alertRepository"); +const io_1 = require("../socket/io"); +class AlertService { + constructor() { + this.repo = new alertRepository_1.AlertRepository(); + } + async create(userId, message, link) { + const alert = await this.repo.createAlert({ userId, message, link }); + const io = (0, io_1.getIo)(); + io.to(`user:${userId}`).emit("newAlert", alert); + return alert; + } + async list(userId) { + return this.repo.findByUserId(userId); + } + async read(alertId, userId) { + const alert = await this.repo.findById(alertId); + if (!alert) + return false; + if (alert.userId !== userId) { + return false; + } + await this.repo.markAsRead(alertId); + return true; + } + async countUnread(userId) { + return this.repo.countUnread(userId); + } +} +exports.AlertService = AlertService; +//# sourceMappingURL=alertService.js.map \ No newline at end of file diff --git a/mission 10/dist/services/alertService.js.map b/mission 10/dist/services/alertService.js.map new file mode 100644 index 000000000..4d3bdc2d9 --- /dev/null +++ b/mission 10/dist/services/alertService.js.map @@ -0,0 +1 @@ +{"version":3,"file":"alertService.js","sourceRoot":"","sources":["../../src/services/alertService.ts"],"names":[],"mappings":";;;AAAA,qEAAkE;AAClE,qCAAqC;AAErC,MAAa,YAAY;IAAzB;QACU,SAAI,GAAG,IAAI,iCAAe,EAAE,CAAC;IAgCvC,CAAC;IA9BC,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,OAAe,EAAE,IAAa;QACzD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAErE,MAAM,EAAE,GAAG,IAAA,UAAK,GAAE,CAAC;QACnB,EAAE,CAAC,EAAE,CAAC,QAAQ,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAEhD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc;QACvB,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAe,EAAE,MAAc;QACxC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAEhD,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QAEzB,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC5B,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAEpC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAc;QAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;CACF;AAjCD,oCAiCC"} \ No newline at end of file diff --git a/mission 10/dist/services/articleService.js b/mission 10/dist/services/articleService.js new file mode 100644 index 000000000..7994cc86b --- /dev/null +++ b/mission 10/dist/services/articleService.js @@ -0,0 +1,45 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ArticleService = void 0; +const articleRepository_1 = require("../repositories/articleRepository"); +class ArticleService { + constructor() { + this.repo = new articleRepository_1.ArticleRepository(); + } + async create(userId, data) { + return this.repo.createArticle({ ...data, userId }); + } + async list({ page, pageSize, keyword }) { + const where = keyword + ? { + OR: [ + { title: { contains: keyword, mode: "insensitive" } }, + { content: { contains: keyword, mode: "insensitive" } }, + ], + } + : {}; + return this.repo.findMany(where, (page - 1) * pageSize, pageSize); + } + async getDetail(id) { + return this.repo.findById(id); + } + async update(userId, data, articleId) { + const article = await this.repo.findById(articleId); + if (!article) + throw new Error("NOT_FOUND"); + if (article.userId !== userId) + throw new Error("FORBIDDEN"); + return this.repo.updatedArticle(articleId, data); + } + async delete(userId, articleId) { + const article = await this.repo.findById(articleId); + if (!article) + throw new Error("NOT_FOUND"); + if (article.userId !== userId) + throw new Error("FORBIDDEN"); + await this.repo.deleteArticle(articleId); + } +} +exports.ArticleService = ArticleService; +exports.default = new ArticleService(); +//# sourceMappingURL=articleService.js.map \ No newline at end of file diff --git a/mission 10/dist/services/articleService.js.map b/mission 10/dist/services/articleService.js.map new file mode 100644 index 000000000..1a6b30fb3 --- /dev/null +++ b/mission 10/dist/services/articleService.js.map @@ -0,0 +1 @@ +{"version":3,"file":"articleService.js","sourceRoot":"","sources":["../../src/services/articleService.ts"],"names":[],"mappings":";;;AAAA,yEAAsE;AAItE,MAAa,cAAc;IAA3B;QACU,SAAI,GAAG,IAAI,qCAAiB,EAAE,CAAC;IAsCzC,CAAC;IApCC,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,IAAsB;QACjD,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAmB;QACrD,MAAM,KAAK,GAA6B,OAAO;YAC7C,CAAC,CAAC;gBACE,EAAE,EAAE;oBACF,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE;oBACrD,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE;iBACxD;aACF;YACH,CAAC,CAAC,EAAE,CAAC;QAEP,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,EAAU;QACxB,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,IAAsB,EAAE,SAAiB;QACpE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QACpD,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;QAC3C,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;QAE5D,OAAO,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,SAAiB;QAC5C,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QACpD,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;QAC3C,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;QAE5D,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAC3C,CAAC;CACF;AAvCD,wCAuCC;AAED,kBAAe,IAAI,cAAc,EAAE,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/services/commentService.js b/mission 10/dist/services/commentService.js new file mode 100644 index 000000000..61ec54707 --- /dev/null +++ b/mission 10/dist/services/commentService.js @@ -0,0 +1,61 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CommentService = void 0; +const commentRepository_1 = require("../repositories/commentRepository"); +const articleRepository_1 = require("../repositories/articleRepository"); +const productRepository_1 = require("../repositories/productRepository"); +const alertService_1 = require("../services/alertService"); +class CommentService { + constructor() { + this.repo = new commentRepository_1.CommentRepository(); + this.articleRepo = new articleRepository_1.ArticleRepository(); + this.productRepo = new productRepository_1.ProductRepository(); + this.alertService = new alertService_1.AlertService(); + } + async createArticleComment(userId, articleId, content) { + const article = await this.articleRepo.findById(articleId); + if (!article) { + throw new Error("Article not found"); + } + const comment = await this.repo.createArticleComment(userId, articleId, content); + if (article && article.userId !== userId) { + await this.alertService.create(article.userId, "내 게시글에 새로운 댓글이 달렸습니다.", `/articles/${articleId}`); + } + return comment; + } + async createProductComment(userId, productId, content) { + const product = await this.productRepo.findById(productId); + if (!product) { + throw new Error("Product not found"); + } + const comment = await this.repo.createProductComment(userId, productId, content); + if (product && product.userId !== userId) { + await this.alertService.create(product.userId, "내 판매글에 새로운 댓글이 달렸습니다.", `/products/${productId}`); + } + return comment; + } + async updateComment(userId, commentId, content) { + const comment = await this.repo.findById(commentId); + if (!comment) + throw new Error("NOT_FOUND"); + if (comment.userId !== userId) + throw new Error("FORBIDDEN"); + return this.repo.updateComment(commentId, content); + } + async deleteComment(userId, commentId) { + const comment = await this.repo.findById(commentId); + if (!comment) + throw new Error("NOT_FOUND"); + if (comment.userId !== userId) + throw new Error("FORBIDDEN"); + await this.repo.deleteComment(commentId); + } + async getProductComments(productId, lastId) { + return this.repo.findProductComments(productId, lastId); + } + async getArticleComments(articleId, lastId) { + return this.repo.findArticleComments(articleId, lastId); + } +} +exports.CommentService = CommentService; +//# sourceMappingURL=commentService.js.map \ No newline at end of file diff --git a/mission 10/dist/services/commentService.js.map b/mission 10/dist/services/commentService.js.map new file mode 100644 index 000000000..c7937b3e7 --- /dev/null +++ b/mission 10/dist/services/commentService.js.map @@ -0,0 +1 @@ +{"version":3,"file":"commentService.js","sourceRoot":"","sources":["../../src/services/commentService.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/mission 10/dist/services/likeService.js b/mission 10/dist/services/likeService.js new file mode 100644 index 000000000..bab15de1c --- /dev/null +++ b/mission 10/dist/services/likeService.js @@ -0,0 +1,37 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LikeService = void 0; +const likeRepository_1 = require("../repositories/likeRepository"); +class LikeService { + constructor() { + this.repo = new likeRepository_1.LikeRepository(); + } + async likeArticle(userId, articleId) { + const article = await this.repo.findArticle(articleId); + if (!article) + throw new Error("ARTICLE_NOT_FOUND"); + const existing = await this.repo.findArticleLike(userId, articleId); + if (existing) { + return this.repo.toggleArticleLike(userId, articleId, existing.like); + } + return this.repo.createArticleLike(userId, articleId); + } + async likeProduct(userId, productId) { + const product = await this.repo.findProduct(productId); + if (!product) + throw new Error("PRODUCT_NOT_FOUND"); + const existing = await this.repo.findProductLike(userId, productId); + if (existing) { + return this.repo.toggleProductLike(userId, productId, existing.like); + } + return this.repo.createProductLike(userId, productId); + } + async getLikedArticles(userId) { + return this.repo.findLikedArticles(userId); + } + async getLikedProducts(userId) { + return this.repo.findLikedProducts(userId); + } +} +exports.LikeService = LikeService; +//# sourceMappingURL=likeService.js.map \ No newline at end of file diff --git a/mission 10/dist/services/likeService.js.map b/mission 10/dist/services/likeService.js.map new file mode 100644 index 000000000..f3598c9e3 --- /dev/null +++ b/mission 10/dist/services/likeService.js.map @@ -0,0 +1 @@ +{"version":3,"file":"likeService.js","sourceRoot":"","sources":["../../src/services/likeService.ts"],"names":[],"mappings":";;;AAAA,mEAAgE;AAEhE,MAAa,WAAW;IAAxB;QACU,SAAI,GAAG,IAAI,+BAAc,EAAE,CAAC;IA+BtC,CAAC;IA7BC,KAAK,CAAC,WAAW,CAAC,MAAc,EAAE,SAAiB;QACjD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QACvD,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAEnD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACpE,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAc,EAAE,SAAiB;QACjD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QACvD,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAEnD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACpE,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,MAAc;QACnC,OAAO,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,MAAc;QACnC,OAAO,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC;CACF;AAhCD,kCAgCC"} \ No newline at end of file diff --git a/mission 10/dist/services/productService.js b/mission 10/dist/services/productService.js new file mode 100644 index 000000000..97fb4a2b1 --- /dev/null +++ b/mission 10/dist/services/productService.js @@ -0,0 +1,57 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ProductService = void 0; +const productRepository_1 = require("../repositories/productRepository"); +const likeRepository_1 = require("../repositories/likeRepository"); +const alertService_1 = require("../services/alertService"); +class ProductService { + constructor() { + this.repo = new productRepository_1.ProductRepository(); + this.likeRepo = new likeRepository_1.LikeRepository(); + this.alertService = new alertService_1.AlertService(); + } + async create(userId, data) { + return this.repo.createProduct({ ...data, userId }); + } + async list({ page, pageSize, keyword }) { + const where = keyword + ? { + OR: [ + { name: { contains: keyword, mode: "insensitive" } }, + { description: { contains: keyword, mode: "insensitive" } }, + ], + } + : {}; + return this.repo.findMany(where, (page - 1) * pageSize, pageSize); + } + async getDetail(id) { + return this.repo.findById(id); + } + async update(userId, productId, data) { + const product = await this.repo.findById(productId); + if (!product) + throw new Error("NOT_FOUND"); + if (product.userId !== userId) + throw new Error("FORBIDDEN"); + const oldPrice = product.price; + const updated = await this.repo.updateProduct(productId, data); + if (data.price !== undefined && data.price !== oldPrice) { + const likedUsers = await this.likeRepo.findUsersWhoLikedProduct(productId); + const targetUsers = likedUsers.filter((u) => u.id !== userId); + for (const user of targetUsers) { + await this.alertService.create(user.id, `좋아요한 상품 "${updated.name}"의 가격이 ${oldPrice}원 → ${data.price}원으로 변경되었습니다.`, `/products/${productId}`); + } + } + return updated; + } + async delete(userId, productId) { + const product = await this.repo.findById(productId); + if (!product) + throw new Error("NOT_FOUND"); + if (product.userId !== userId) + throw new Error("FORBIDDEN"); + await this.repo.deleteProduct(productId); + } +} +exports.ProductService = ProductService; +//# sourceMappingURL=productService.js.map \ No newline at end of file diff --git a/mission 10/dist/services/productService.js.map b/mission 10/dist/services/productService.js.map new file mode 100644 index 000000000..b1c703d0d --- /dev/null +++ b/mission 10/dist/services/productService.js.map @@ -0,0 +1 @@ +{"version":3,"file":"productService.js","sourceRoot":"","sources":["../../src/services/productService.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/mission 10/dist/services/userService.js b/mission 10/dist/services/userService.js new file mode 100644 index 000000000..171b7b32b --- /dev/null +++ b/mission 10/dist/services/userService.js @@ -0,0 +1,50 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UserService = void 0; +const bcrypt_1 = __importDefault(require("bcrypt")); +const userRepository_1 = require("../repositories/userRepository"); +const token_1 = require("../lib/token"); +class UserService { + constructor() { + this.userRepo = new userRepository_1.UserRepository(); + } + async register(data) { + const exists = await this.userRepo.findByEmail(data.email); + if (exists) + throw new Error("EMAIL_EXISTS"); + const salt = await bcrypt_1.default.genSalt(10); + const hashedPassword = await bcrypt_1.default.hash(data.password, salt); + await this.userRepo.createUser(data.email, data.nickname, hashedPassword); + return { message: "User registered successfully" }; + } + async getProfile(userId) { + return this.userRepo.findById(userId); + } + async updateInformation(userId, nickname, image) { + const updateData = {}; + if (nickname) + updateData.nickname = nickname; + if (image) + updateData.image = image; + if (Object.keys(updateData).length === 0) + throw new Error("NO_DATA"); + return this.userRepo.updateUser(userId, updateData); + } + async updatePassword(userId, data) { + const salt = await bcrypt_1.default.genSalt(10); + const hashedPassword = await bcrypt_1.default.hash(data.password, salt); + await this.userRepo.updateUser(userId, { password: hashedPassword }); + return { message: "Password updated successfully" }; + } + async getProducts(userId) { + return this.userRepo.findProductsByUserId(userId); + } + generateUserTokens(userId) { + return (0, token_1.generateTokens)(userId); + } +} +exports.UserService = UserService; +//# sourceMappingURL=userService.js.map \ No newline at end of file diff --git a/mission 10/dist/services/userService.js.map b/mission 10/dist/services/userService.js.map new file mode 100644 index 000000000..12a9ab0f9 --- /dev/null +++ b/mission 10/dist/services/userService.js.map @@ -0,0 +1 @@ +{"version":3,"file":"userService.js","sourceRoot":"","sources":["../../src/services/userService.ts"],"names":[],"mappings":";;;;;;AAAA,oDAA4B;AAC5B,mEAAgE;AAChE,wCAA8C;AAG9C,MAAa,WAAW;IAAxB;QACU,aAAQ,GAAG,IAAI,+BAAc,EAAE,CAAC;IAyC1C,CAAC;IAvCC,KAAK,CAAC,QAAQ,CAAC,IAAqB;QAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3D,IAAI,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;QAE5C,MAAM,IAAI,GAAG,MAAM,gBAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACtC,MAAM,cAAc,GAAG,MAAM,gBAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAE9D,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QAC1E,OAAO,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAc;QAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,MAAc,EAAE,QAAiB,EAAE,KAAc;QACvE,MAAM,UAAU,GAA2B,EAAE,CAAC;QAC9C,IAAI,QAAQ;YAAE,UAAU,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC7C,IAAI,KAAK;YAAE,UAAU,CAAC,KAAK,GAAG,KAAK,CAAC;QAEpC,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;QAErE,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,MAAc,EAAE,IAAqB;QACxD,MAAM,IAAI,GAAG,MAAM,gBAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACtC,MAAM,cAAc,GAAG,MAAM,gBAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC9D,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC;QACrE,OAAO,EAAE,OAAO,EAAE,+BAA+B,EAAE,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAc;QAC9B,OAAO,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;IACpD,CAAC;IAED,kBAAkB,CAAC,MAAc;QAC/B,OAAO,IAAA,sBAAc,EAAC,MAAM,CAAC,CAAC;IAChC,CAAC;CACF;AA1CD,kCA0CC"} \ No newline at end of file diff --git a/mission 10/dist/socket/io.js b/mission 10/dist/socket/io.js new file mode 100644 index 000000000..a5f05948b --- /dev/null +++ b/mission 10/dist/socket/io.js @@ -0,0 +1,22 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.initIo = initIo; +exports.getIo = getIo; +const socket_io_1 = require("socket.io"); +let io = null; +function initIo(server) { + io = new socket_io_1.Server(server, { + cors: { + origin: "http://localhost:3000", + methods: ["GET", "POST"], + }, + }); + return io; +} +function getIo() { + if (!io) { + throw new Error("Socket.io has not been initialized!"); + } + return io; +} +//# sourceMappingURL=io.js.map \ No newline at end of file diff --git a/mission 10/dist/socket/io.js.map b/mission 10/dist/socket/io.js.map new file mode 100644 index 000000000..7d0628922 --- /dev/null +++ b/mission 10/dist/socket/io.js.map @@ -0,0 +1 @@ +{"version":3,"file":"io.js","sourceRoot":"","sources":["../../src/socket/io.ts"],"names":[],"mappings":";;AAIA,wBAQC;AAED,sBAKC;AAnBD,yCAAmC;AAEnC,IAAI,EAAE,GAAkB,IAAI,CAAC;AAE7B,SAAgB,MAAM,CAAC,MAAW;IAChC,EAAE,GAAG,IAAI,kBAAM,CAAC,MAAM,EAAE;QACtB,IAAI,EAAE;YACJ,MAAM,EAAE,uBAAuB;YAC/B,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC;SACzB;KACF,CAAC,CAAC;IACH,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAgB,KAAK;IACnB,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"} \ No newline at end of file diff --git a/mission 10/dist/socket/socket.js b/mission 10/dist/socket/socket.js new file mode 100644 index 000000000..ea2f2987d --- /dev/null +++ b/mission 10/dist/socket/socket.js @@ -0,0 +1,25 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.registerSocket = registerSocket; +const io_1 = require("./io"); +const jsonwebtoken_1 = __importDefault(require("jsonwebtoken")); +function registerSocket() { + const io = (0, io_1.getIo)(); + io.on("connection", (socket) => { + console.log("Socket connected:", socket.id); + const token = socket.handshake.auth?.token; + if (!token) + return socket.disconnect(); + try { + const decoded = jsonwebtoken_1.default.verify(token, process.env.JWT_SECRET); + socket.join(`user:${decoded.id}`); + } + catch (err) { + socket.disconnect(); + } + }); +} +//# sourceMappingURL=socket.js.map \ No newline at end of file diff --git a/mission 10/dist/socket/socket.js.map b/mission 10/dist/socket/socket.js.map new file mode 100644 index 000000000..cfb631795 --- /dev/null +++ b/mission 10/dist/socket/socket.js.map @@ -0,0 +1 @@ +{"version":3,"file":"socket.js","sourceRoot":"","sources":["../../src/socket/socket.ts"],"names":[],"mappings":";;;;;AAGA,wCAmBC;AAtBD,6BAA6B;AAC7B,gEAA+B;AAE/B,SAAgB,cAAc;IAC5B,MAAM,EAAE,GAAG,IAAA,UAAK,GAAE,CAAC;IAEnB,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,EAAE;QAC7B,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QAE5C,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC;QAC3C,IAAI,CAAC,KAAK;YAAE,OAAO,MAAM,CAAC,UAAU,EAAE,CAAC;QAEvC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,sBAAG,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,UAAW,CAExD,CAAC;YAEF,MAAM,CAAC,IAAI,CAAC,QAAQ,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/mission 10/package.json b/mission 10/package.json index 93551d7a7..b3a5339ad 100644 --- a/mission 10/package.json +++ b/mission 10/package.json @@ -4,12 +4,13 @@ "main": "index.js", "scripts": { "dev": "ts-node --files src/server.ts", - "start": "node dist/app.js", + "start": "node dist/server.js", "lint": "eslint . --ext .ts", "prisma:generate": "prisma generate", "prisma:migrate": "prisma migrate dev", "test": "jest --coverage", - "test:watch": "jest --watch" + "test:watch": "jest --watch", + "build": "tsc" }, "author": "", "license": "ISC", diff --git a/mission 9/package-lock.json b/mission 9/package-lock.json index 88d9d3424..9a3e17c01 100644 --- a/mission 9/package-lock.json +++ b/mission 9/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "@aws-sdk/client-s3": "^3.933.0", "@prisma/client": "^6.13.0", "bcrypt": "^6.0.0", "cookie-parser": "^1.4.7", @@ -37,7 +38,7 @@ "@types/passport": "^1.0.17", "@types/passport-jwt": "^4.0.1", "@types/passport-local": "^1.0.38", - "jest": "^30.2.0", + "jest": "^29.7.0", "prisma": "^6.15.0", "ts-jest": "^29.4.5", "ts-node": "^10.9.2", @@ -45,4438 +46,8785 @@ "typescript": "^5.9.3" } }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", - "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/@babel/core": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", - "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", - "dev": true, - "license": "MIT", - "peer": true, + "node_modules/@aws-crypto/crc32c": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", + "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", + "license": "Apache-2.0", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5", - "@jridgewell/remapping": "^2.3.5", - "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" + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" } }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@aws-crypto/sha1-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", + "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" } }, - "node_modules/@babel/generator": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", - "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.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, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" } }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/parser": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", - "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", "dependencies": { - "@babel/types": "^7.28.5" - }, - "bin": { - "parser": "bin/babel-parser.js" + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=14.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, - "license": "MIT", + "node_modules/@aws-sdk/client-s3": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.933.0.tgz", + "integrity": "sha512-KxwZvdxdCeWK6o8mpnb+kk7Kgb8V+8AjTwSXUWH1UAD85B0tjdo1cSfE5zoR5fWGol4Ml5RLez12a6LPhsoTqA==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.932.0", + "@aws-sdk/credential-provider-node": "3.933.0", + "@aws-sdk/middleware-bucket-endpoint": "3.930.0", + "@aws-sdk/middleware-expect-continue": "3.930.0", + "@aws-sdk/middleware-flexible-checksums": "3.932.0", + "@aws-sdk/middleware-host-header": "3.930.0", + "@aws-sdk/middleware-location-constraint": "3.930.0", + "@aws-sdk/middleware-logger": "3.930.0", + "@aws-sdk/middleware-recursion-detection": "3.933.0", + "@aws-sdk/middleware-sdk-s3": "3.932.0", + "@aws-sdk/middleware-ssec": "3.930.0", + "@aws-sdk/middleware-user-agent": "3.932.0", + "@aws-sdk/region-config-resolver": "3.930.0", + "@aws-sdk/signature-v4-multi-region": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@aws-sdk/util-endpoints": "3.930.0", + "@aws-sdk/util-user-agent-browser": "3.930.0", + "@aws-sdk/util-user-agent-node": "3.932.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.2", + "@smithy/eventstream-serde-browser": "^4.2.5", + "@smithy/eventstream-serde-config-resolver": "^4.3.5", + "@smithy/eventstream-serde-node": "^4.2.5", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-blob-browser": "^4.2.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/hash-stream-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/md5-js": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.9", + "@smithy/middleware-retry": "^4.4.9", + "@smithy/middleware-serde": "^4.2.5", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.5", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.8", + "@smithy/util-defaults-mode-node": "^4.2.11", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-stream": "^4.5.6", + "@smithy/util-utf8": "^4.2.0", + "@smithy/util-waiter": "^4.2.5", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.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, - "license": "MIT", + "node_modules/@aws-sdk/client-sso": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.933.0.tgz", + "integrity": "sha512-zwGLSiK48z3PzKpQiDMKP85+fpIrPMF1qQOQW9OW7BGj5AuBZIisT2O4VzIgYJeh+t47MLU7VgBQL7muc+MJDg==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.932.0", + "@aws-sdk/middleware-host-header": "3.930.0", + "@aws-sdk/middleware-logger": "3.930.0", + "@aws-sdk/middleware-recursion-detection": "3.933.0", + "@aws-sdk/middleware-user-agent": "3.932.0", + "@aws-sdk/region-config-resolver": "3.930.0", + "@aws-sdk/types": "3.930.0", + "@aws-sdk/util-endpoints": "3.930.0", + "@aws-sdk/util-user-agent-browser": "3.930.0", + "@aws-sdk/util-user-agent-node": "3.932.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.2", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.9", + "@smithy/middleware-retry": "^4.4.9", + "@smithy/middleware-serde": "^4.2.5", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.5", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.8", + "@smithy/util-defaults-mode-node": "^4.2.11", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.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, - "license": "MIT", + "node_modules/@aws-sdk/core": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.932.0.tgz", + "integrity": "sha512-AS8gypYQCbNojwgjvZGkJocC2CoEICDx9ZJ15ILsv+MlcCVLtUJSRSx3VzJOUY2EEIaGLRrPNlIqyn/9/fySvA==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "@aws-sdk/types": "3.930.0", + "@aws-sdk/xml-builder": "3.930.0", + "@smithy/core": "^3.18.2", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/signature-v4": "^5.3.5", + "@smithy/smithy-client": "^4.9.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.932.0.tgz", + "integrity": "sha512-ozge/c7NdHUDyHqro6+P5oHt8wfKSUBN+olttiVfBe9Mw3wBMpPa3gQ0pZnG+gwBkKskBuip2bMR16tqYvUSEA==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@aws-sdk/core": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", - "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.932.0.tgz", + "integrity": "sha512-b6N9Nnlg8JInQwzBkUq5spNaXssM3h3zLxGzpPrnw0nHSIWPJPTbZzA5Ca285fcDUFuKP+qf3qkuqlAjGOdWhg==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@aws-sdk/core": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.5", + "@smithy/types": "^4.9.0", + "@smithy/util-stream": "^4.5.6", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.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, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.933.0.tgz", + "integrity": "sha512-HygGyKuMG5AaGXsmM0d81miWDon55xwalRHB3UmDg3QBhtunbNIoIaWUbNTKuBZXcIN6emeeEZw/YgSMqLc0YA==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@aws-sdk/core": "3.932.0", + "@aws-sdk/credential-provider-env": "3.932.0", + "@aws-sdk/credential-provider-http": "3.932.0", + "@aws-sdk/credential-provider-process": "3.932.0", + "@aws-sdk/credential-provider-sso": "3.933.0", + "@aws-sdk/credential-provider-web-identity": "3.933.0", + "@aws-sdk/nested-clients": "3.933.0", + "@aws-sdk/types": "3.930.0", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.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, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.933.0.tgz", + "integrity": "sha512-L2dE0Y7iMLammQewPKNeEh1z/fdJyYEU+/QsLBD9VEh+SXcN/FIyTi21Isw8wPZN6lMB9PDVtISzBnF8HuSFrw==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-sdk/credential-provider-env": "3.932.0", + "@aws-sdk/credential-provider-http": "3.932.0", + "@aws-sdk/credential-provider-ini": "3.933.0", + "@aws-sdk/credential-provider-process": "3.932.0", + "@aws-sdk/credential-provider-sso": "3.933.0", + "@aws-sdk/credential-provider-web-identity": "3.933.0", + "@aws-sdk/types": "3.930.0", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.932.0.tgz", + "integrity": "sha512-BodZYKvT4p/Dkm28Ql/FhDdS1+p51bcZeMMu2TRtU8PoMDHnVDhHz27zASEKSZwmhvquxHrZHB0IGuVqjZUtSQ==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@aws-sdk/core": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.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, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.933.0.tgz", + "integrity": "sha512-/R1DBR7xNcuZIhS2RirU+P2o8E8/fOk+iLAhbqeSTq+g09fP/F6W7ouFpS5eVE2NIfWG7YBFoVddOhvuqpn51g==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@aws-sdk/client-sso": "3.933.0", + "@aws-sdk/core": "3.932.0", + "@aws-sdk/token-providers": "3.933.0", + "@aws-sdk/types": "3.930.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.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, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.933.0.tgz", + "integrity": "sha512-c7Eccw2lhFx2/+qJn3g+uIDWRuWi2A6Sz3PVvckFUEzPsP0dPUo19hlvtarwP5GzrsXn0yEPRVhpewsIaSCGaQ==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-sdk/core": "3.932.0", + "@aws-sdk/nested-clients": "3.933.0", + "@aws-sdk/types": "3.930.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.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, - "license": "MIT", + "node_modules/@aws-sdk/middleware-bucket-endpoint": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.930.0.tgz", + "integrity": "sha512-cnCLWeKPYgvV4yRYPFH6pWMdUByvu2cy2BAlfsPpvnm4RaVioztyvxmQj5PmVN5fvWs5w/2d6U7le8X9iye2sA==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@aws-sdk/types": "3.930.0", + "@aws-sdk/util-arn-parser": "3.893.0", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-config-provider": "^4.2.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.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, - "license": "MIT", + "node_modules/@aws-sdk/middleware-expect-continue": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.930.0.tgz", + "integrity": "sha512-5HEQ+JU4DrLNWeY27wKg/jeVa8Suy62ivJHOSUf6e6hZdVIMx0h/kXS1fHEQNNiLu2IzSEP/bFXsKBaW7x7s0g==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-sdk/types": "3.930.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.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, - "license": "MIT", + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.932.0.tgz", + "integrity": "sha512-hyvRz/XS/0HTHp9/Ld1mKwpOi7bZu5olI42+T112rkCTbt1bewkygzEl4oflY4H7cKMamQusYoL0yBUD/QSEvA==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-crypto/util": "5.2.0", + "@aws-sdk/core": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@smithy/is-array-buffer": "^4.2.0", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-stream": "^4.5.6", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.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, - "license": "MIT", + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.930.0.tgz", + "integrity": "sha512-x30jmm3TLu7b/b+67nMyoV0NlbnCVT5DI57yDrhXAPCtdgM1KtdLWt45UcHpKOm1JsaIkmYRh2WYu7Anx4MG0g==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-sdk/types": "3.930.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/middleware-location-constraint": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.930.0.tgz", + "integrity": "sha512-QIGNsNUdRICog+LYqmtJ03PLze6h2KCORXUs5td/hAEjVP5DMmubhtrGg1KhWyctACluUH/E/yrD14p4pRXxwA==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@aws-sdk/types": "3.930.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.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, - "license": "MIT", + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.930.0.tgz", + "integrity": "sha512-vh4JBWzMCBW8wREvAwoSqB2geKsZwSHTa0nSt0OMOLp2PdTYIZDi0ZiVMmpfnjcx9XbS6aSluLv9sKx4RrG46A==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@aws-sdk/types": "3.930.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.933.0.tgz", + "integrity": "sha512-qgrMlkVKzTCAdNw2A05DC2sPBo0KRQ7wk+lbYSRJnWVzcrceJhnmhoZVV5PFv7JtchK7sHVcfm9lcpiyd+XaCA==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@aws-sdk/types": "3.930.0", + "@aws/lambda-invoke-store": "^0.2.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.0.0" } }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.932.0.tgz", + "integrity": "sha512-bYMHxqQzseaAP9Z5qLI918z5AtbAnZRRtFi3POb4FLZyreBMgCgBNaPkIhdgywnkqaydTWvbMBX4s9f4gUwlTw==", + "license": "Apache-2.0", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "@aws-sdk/core": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@aws-sdk/util-arn-parser": "3.893.0", + "@smithy/core": "^3.18.2", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/signature-v4": "^5.3.5", + "@smithy/smithy-client": "^4.9.5", + "@smithy/types": "^4.9.0", + "@smithy/util-config-provider": "^4.2.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-stream": "^4.5.6", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/traverse": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", - "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/middleware-ssec": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.930.0.tgz", + "integrity": "sha512-N2/SvodmaDS6h7CWfuapt3oJyn1T2CBz0CsDIiTDv9cSagXAVFjPdm2g4PFJqrNBeqdDIoYBnnta336HmamWHg==", + "license": "Apache-2.0", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.5", - "debug": "^4.3.1" + "@aws-sdk/types": "3.930.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/types": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", - "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.932.0.tgz", + "integrity": "sha512-9BGTbJyA/4PTdwQWE9hAFIJGpsYkyEW20WON3i15aDqo5oRZwZmqaVageOD57YYqG8JDJjvcwKyDdR4cc38dvg==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" + "@aws-sdk/core": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@aws-sdk/util-endpoints": "3.930.0", + "@smithy/core": "^3.18.2", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.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, - "license": "MIT" - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/nested-clients": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.933.0.tgz", + "integrity": "sha512-o1GX0+IPlFi/D8ei9y/jj3yucJWNfPnbB5appVBWevAyUdZA5KzQ2nK/hDxiu9olTZlFEFpf1m1Rn3FaGxHqsw==", + "license": "Apache-2.0", "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.932.0", + "@aws-sdk/middleware-host-header": "3.930.0", + "@aws-sdk/middleware-logger": "3.930.0", + "@aws-sdk/middleware-recursion-detection": "3.933.0", + "@aws-sdk/middleware-user-agent": "3.932.0", + "@aws-sdk/region-config-resolver": "3.930.0", + "@aws-sdk/types": "3.930.0", + "@aws-sdk/util-endpoints": "3.930.0", + "@aws-sdk/util-user-agent-browser": "3.930.0", + "@aws-sdk/util-user-agent-node": "3.932.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.2", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.9", + "@smithy/middleware-retry": "^4.4.9", + "@smithy/middleware-serde": "^4.2.5", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.5", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.8", + "@smithy/util-defaults-mode-node": "^4.2.11", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=12" + "node": ">=18.0.0" } }, - "node_modules/@emnapi/core": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.0.tgz", - "integrity": "sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw==", - "dev": true, - "license": "MIT", - "optional": true, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.930.0.tgz", + "integrity": "sha512-KL2JZqH6aYeQssu1g1KuWsReupdfOoxD6f1as2VC+rdwYFUu4LfzMsFfXnBvvQWWqQ7rZHWOw1T+o5gJmg7Dzw==", + "license": "Apache-2.0", "dependencies": { - "@emnapi/wasi-threads": "1.1.0", - "tslib": "^2.4.0" + "@aws-sdk/types": "3.930.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@emnapi/runtime": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.0.tgz", - "integrity": "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q==", - "dev": true, - "license": "MIT", - "optional": true, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.932.0.tgz", + "integrity": "sha512-NCIRJvoRc9246RZHIusY1+n/neeG2yGhBGdKhghmrNdM+mLLN6Ii7CKFZjx3DhxtpHMpl1HWLTMhdVrGwP2upw==", + "license": "Apache-2.0", "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", - "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" + "@aws-sdk/middleware-sdk-s3": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/signature-v4": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", - "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], + "node_modules/@aws-sdk/token-providers": { + "version": "3.933.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.933.0.tgz", + "integrity": "sha512-Qzq7zj9yXUgAAJEbbmqRhm0jmUndl8nHG0AbxFEfCfQRVZWL96Qzx0mf8lYwT9hIMrXncLwy31HOthmbXwFRwQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.932.0", + "@aws-sdk/nested-clients": "3.933.0", + "@aws-sdk/types": "3.930.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", - "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "node_modules/@aws-sdk/types": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.930.0.tgz", + "integrity": "sha512-we/vaAgwlEFW7IeftmCLlLMw+6hFs3DzZPJw7lVHbj/5HJ0bz9gndxEsS2lQoeJ1zhiiLqAqvXxmM43s0MBg0A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", - "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "node_modules/@aws-sdk/util-arn-parser": { + "version": "3.893.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.893.0.tgz", + "integrity": "sha512-u8H4f2Zsi19DGnwj5FSZzDMhytYF/bCh37vAtBsn3cNDL3YG578X5oc+wSX54pM3tOxS+NY7tvOAo52SW7koUA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", - "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.930.0.tgz", + "integrity": "sha512-M2oEKBzzNAYr136RRc6uqw3aWlwCxqTP1Lawps9E1d2abRPvl1p1ztQmmXp1Ak4rv8eByIZ+yQyKQ3zPdRG5dw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.930.0", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-endpoints": "^3.2.5", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", - "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.893.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.893.0.tgz", + "integrity": "sha512-T89pFfgat6c8nMmpI8eKjBcDcgJq36+m9oiXbcUzeU55MP9ZuGgBomGjGnHaEyF36jenW9gmg3NfZDm0AO2XPg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", - "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.930.0.tgz", + "integrity": "sha512-q6lCRm6UAe+e1LguM5E4EqM9brQlDem4XDcQ87NzEvlTW6GzmNCO0w1jS0XgCFXQHjDxjdlNFX+5sRbHijwklg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.930.0", + "@smithy/types": "^4.9.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", - "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.932.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.932.0.tgz", + "integrity": "sha512-/kC6cscHrZL74TrZtgiIL5jJNbVsw9duGGPurmaVgoCbP7NnxyaSWEurbNV3VPNPhNE3bV3g4Ci+odq+AlsYQg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.932.0", + "@aws-sdk/types": "3.930.0", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", - "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "node_modules/@aws-sdk/xml-builder": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.930.0.tgz", + "integrity": "sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "fast-xml-parser": "5.2.5", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", - "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "node_modules/@aws/lambda-invoke-store": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.0.tgz", + "integrity": "sha512-D1jAmAZQYMoPiacfgNf7AWhg3DFN3Wq/vQv3WINt9znwjzHp2x+WzdJFxxj7xZL7V1U79As6G8f7PorMYWBKsQ==", + "license": "Apache-2.0", "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", - "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", - "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", - "cpu": [ - "ia32" - ], + "node_modules/@babel/compat-data": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", - "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", - "cpu": [ - "loong64" - ], + "node_modules/@babel/core": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/remapping": "^2.3.5", + "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": ">=18" + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", - "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", - "cpu": [ - "mips64el" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", - "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/generator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", - "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", - "cpu": [ - "riscv64" - ], + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", - "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", - "cpu": [ - "s390x" - ], + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", - "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", - "cpu": [ - "x64" - ], + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", - "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", - "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", - "cpu": [ - "x64" - ], + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", - "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", - "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", - "cpu": [ - "x64" - ], + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", - "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", - "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", - "cpu": [ - "x64" - ], + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", - "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", - "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", - "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", - "cpu": [ - "x64" - ], + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, "engines": { - "node": ">=18" + "node": ">=6.0.0" } }, - "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==", + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, - "license": "ISC", + "license": "MIT", "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" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=12" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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, - "license": "MIT" - }, - "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==", + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "dev": true, "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" + "@babel/helper-plugin-utils": "^7.10.4" }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, - "license": "ISC", + "license": "MIT", "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" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/console": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.2.0.tgz", - "integrity": "sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==", + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", - "@types/node": "*", - "chalk": "^4.1.2", - "jest-message-util": "30.2.0", - "jest-util": "30.2.0", - "slash": "^3.0.0" + "@babel/helper-plugin-utils": "^7.10.4" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/core": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.2.0.tgz", - "integrity": "sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==", + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.2.0", - "@jest/pattern": "30.0.1", - "@jest/reporters": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", - "@types/node": "*", - "ansi-escapes": "^4.3.2", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "exit-x": "^0.2.2", - "graceful-fs": "^4.2.11", - "jest-changed-files": "30.2.0", - "jest-config": "30.2.0", - "jest-haste-map": "30.2.0", - "jest-message-util": "30.2.0", - "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-resolve-dependencies": "30.2.0", - "jest-runner": "30.2.0", - "jest-runtime": "30.2.0", - "jest-snapshot": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "jest-watcher": "30.2.0", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/diff-sequences": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", - "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, "license": "MIT", - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/environment": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz", - "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==", + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/fake-timers": "30.2.0", - "@jest/types": "30.2.0", - "@types/node": "*", - "jest-mock": "30.2.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/expect": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.2.0.tgz", - "integrity": "sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==", + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, "license": "MIT", "dependencies": { - "expect": "30.2.0", - "jest-snapshot": "30.2.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/expect-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", - "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/get-type": "30.1.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/fake-timers": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz", - "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==", + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", - "@sinonjs/fake-timers": "^13.0.0", - "@types/node": "*", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/get-type": { - "version": "30.1.0", - "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", - "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/globals": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.2.0.tgz", - "integrity": "sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==", + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/expect": "30.2.0", - "@jest/types": "30.2.0", - "jest-mock": "30.2.0" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/pattern": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", - "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "jest-regex-util": "30.0.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/reporters": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.2.0.tgz", - "integrity": "sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==", + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "license": "MIT", "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", - "@jridgewell/trace-mapping": "^0.3.25", - "@types/node": "*", - "chalk": "^4.1.2", - "collect-v8-coverage": "^1.0.2", - "exit-x": "^0.2.2", - "glob": "^10.3.10", - "graceful-fs": "^4.2.11", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^5.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "30.2.0", - "jest-util": "30.2.0", - "jest-worker": "30.2.0", - "slash": "^3.0.0", - "string-length": "^4.0.2", - "v8-to-istanbul": "^9.0.1" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">=6.9.0" } }, - "node_modules/@jest/reporters/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@jest/reporters/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@jest/reporters/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "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, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "license": "MIT" }, - "node_modules/@jest/reporters/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=12" } }, - "node_modules/@jest/schemas": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", - "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", - "dev": true, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "cpu": [ + "ppc64" + ], "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.34.0" - }, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/snapshot-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz", - "integrity": "sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==", - "dev": true, + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "cpu": [ + "arm" + ], "license": "MIT", - "dependencies": { - "@jest/types": "30.2.0", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "natural-compare": "^1.4.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/source-map": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", - "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", - "dev": true, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "callsites": "^3.1.0", - "graceful-fs": "^4.2.11" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@jest/test-result": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.2.0.tgz", - "integrity": "sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==", - "dev": true, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@jest/console": "30.2.0", - "@jest/types": "30.2.0", - "@types/istanbul-lib-coverage": "^2.0.6", - "collect-v8-coverage": "^1.0.2" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/test-sequencer": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.2.0.tgz", - "integrity": "sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==", - "dev": true, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@jest/test-result": "30.2.0", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", - "slash": "^3.0.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/transform": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz", - "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==", - "dev": true, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@babel/core": "^7.27.4", - "@jest/types": "30.2.0", - "@jridgewell/trace-mapping": "^0.3.25", - "babel-plugin-istanbul": "^7.0.1", - "chalk": "^4.1.2", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", - "jest-regex-util": "30.0.1", - "jest-util": "30.2.0", - "micromatch": "^4.0.8", - "pirates": "^4.0.7", - "slash": "^3.0.0", - "write-file-atomic": "^5.0.1" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@jest/types": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", - "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", - "dev": true, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], "license": "MIT", - "dependencies": { - "@jest/pattern": "30.0.1", - "@jest/schemas": "30.0.5", - "@types/istanbul-lib-coverage": "^2.0.6", - "@types/istanbul-reports": "^3.0.4", - "@types/node": "*", - "@types/yargs": "^17.0.33", - "chalk": "^4.1.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@jridgewell/remapping/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.0.0" + "node": ">=18" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "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, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", - "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", - "dev": true, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], "license": "MIT", "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.10.0" + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "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, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], "license": "MIT", "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": ">=18" } }, - "node_modules/@pkgr/core": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", - "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", - "dev": true, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/pkgr" + "node": ">=18" } }, - "node_modules/@prisma/client": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.13.0.tgz", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "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/console/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/console/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, + "license": "MIT", + "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/@jest/console/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, + "license": "MIT" + }, + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console/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, + "license": "MIT", + "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/console/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, + "license": "MIT", + "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/console/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, + "license": "MIT", + "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/@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, + "license": "MIT", + "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/core/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core/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, + "license": "MIT", + "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/core/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, + "license": "MIT", + "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/@jest/core/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/core/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, + "license": "MIT" + }, + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/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, + "license": "MIT", + "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/core/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, + "license": "MIT", + "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/core/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, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core/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, + "license": "MIT", + "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/core/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, + "license": "MIT", + "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/core/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, + "license": "MIT", + "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/@jest/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@jest/core/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@jest/diff-sequences": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", + "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "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, + "license": "MIT", + "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/environment/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/environment/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, + "license": "MIT", + "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/@jest/environment/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, + "license": "MIT" + }, + "node_modules/@jest/environment/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/environment/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, + "license": "MIT", + "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/environment/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, + "license": "MIT", + "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/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "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": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", + "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect/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, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect/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, + "license": "MIT", + "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/@jest/expect/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, + "license": "MIT" + }, + "node_modules/@jest/expect/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/expect/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/expect/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, + "license": "MIT", + "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/@jest/expect/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, + "license": "MIT", + "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/expect/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, + "license": "MIT", + "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/expect/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, + "license": "MIT", + "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/expect/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, + "license": "MIT", + "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/expect/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, + "license": "MIT", + "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/@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, + "license": "MIT", + "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/fake-timers/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers/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, + "license": "MIT", + "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/@jest/fake-timers/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, + "license": "MIT" + }, + "node_modules/@jest/fake-timers/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/fake-timers/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/fake-timers/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, + "license": "MIT", + "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/fake-timers/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, + "license": "MIT", + "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/fake-timers/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, + "license": "MIT", + "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/fake-timers/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, + "license": "MIT", + "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/@jest/get-type": { + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", + "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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, + "license": "MIT", + "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/globals/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals/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, + "license": "MIT", + "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/@jest/globals/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, + "license": "MIT" + }, + "node_modules/@jest/globals/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/globals/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, + "license": "MIT", + "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/globals/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, + "license": "MIT", + "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/pattern": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", + "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-regex-util": "30.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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, + "license": "MIT", + "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/@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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters/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, + "license": "MIT", + "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/reporters/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, + "license": "MIT", + "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/@jest/reporters/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/reporters/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, + "license": "MIT" + }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/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, + "license": "BSD-3-Clause", + "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/@jest/reporters/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/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, + "license": "MIT", + "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/reporters/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, + "license": "MIT", + "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/reporters/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, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters/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, + "license": "MIT", + "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/reporters/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, + "license": "MIT", + "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/reporters/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, + "license": "MIT", + "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/@jest/reporters/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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, + "license": "MIT", + "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/source-map/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "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, + "license": "MIT", + "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-result/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result/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, + "license": "MIT", + "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/@jest/test-result/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, + "license": "MIT" + }, + "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, + "license": "MIT", + "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/test-sequencer/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer/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, + "license": "MIT", + "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/@jest/test-sequencer/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, + "license": "MIT" + }, + "node_modules/@jest/test-sequencer/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/test-sequencer/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, + "license": "MIT", + "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/test-sequencer/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, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer/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, + "license": "MIT", + "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/test-sequencer/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, + "license": "MIT", + "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/test-sequencer/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@jest/transform": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz", + "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/types": "30.2.0", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.1", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-util": "30.2.0", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/types": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", + "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@prisma/client": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.13.0.tgz", "integrity": "sha512-8m2+I3dQovkV8CkDMluiwEV1TxV9EXdT6xaCz39O6jYw7mkf5gwfmi+cL4LJsEPwz5tG7sreBwkRpEMJedGYUQ==", "hasInstallScript": true, "license": "Apache-2.0", "engines": { - "node": ">=18.18" + "node": ">=18.18" + }, + "peerDependencies": { + "prisma": "*", + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@prisma/config": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.15.0.tgz", + "integrity": "sha512-KMEoec9b2u6zX0EbSEx/dRpx1oNLjqJEBZYyK0S3TTIbZ7GEGoVyGyFRk4C72+A38cuPLbfQGQvgOD+gBErKlA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "c12": "3.1.0", + "deepmerge-ts": "7.1.5", + "effect": "3.16.12", + "empathic": "2.0.0" + } + }, + "node_modules/@prisma/debug": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.15.0.tgz", + "integrity": "sha512-y7cSeLuQmyt+A3hstAs6tsuAiVXSnw9T55ra77z0nbNkA8Lcq9rNcQg6PI00by/+WnE/aMRJ/W7sZWn2cgIy1g==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.15.0.tgz", + "integrity": "sha512-opITiR5ddFJ1N2iqa7mkRlohCZqVSsHhRcc29QXeldMljOf4FSellLT0J5goVb64EzRTKcIDeIsJBgmilNcKxA==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/fetch-engine": "6.15.0", + "@prisma/get-platform": "6.15.0" + } + }, + "node_modules/@prisma/engines-version": { + "version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb.tgz", + "integrity": "sha512-a/46aK5j6L3ePwilZYEgYDPrhBQ/n4gYjLxT5YncUTJJNRnTCVjPF86QdzUOLRdYjCLfhtZp9aum90W0J+trrg==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.15.0.tgz", + "integrity": "sha512-xcT5f6b+OWBq6vTUnRCc7qL+Im570CtwvgSj+0MTSGA1o9UDSKZ/WANvwtiRXdbYWECpyC3CukoG3A04VTAPHw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0", + "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", + "@prisma/get-platform": "6.15.0" + } + }, + "node_modules/@prisma/get-platform": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.15.0.tgz", + "integrity": "sha512-Jbb+Xbxyp05NSR1x2epabetHiXvpO8tdN2YNoWoA/ZsbYyxxu/CO/ROBauIFuMXs3Ti+W7N7SJtWsHGaWte9Rg==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.15.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", + "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "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, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.5.tgz", + "integrity": "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.2.0.tgz", + "integrity": "sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.2.1.tgz", + "integrity": "sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-base64": "^4.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.3.tgz", + "integrity": "sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-config-provider": "^4.2.0", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/core": { + "version": "3.18.4", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.18.4.tgz", + "integrity": "sha512-o5tMqPZILBvvROfC8vC+dSVnWJl9a0u9ax1i1+Bq8515eYjUJqqk5XjjEsDLoeL5dSqGSh6WGdVx1eJ1E/Nwhw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/middleware-serde": "^4.2.6", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-stream": "^4.5.6", + "@smithy/util-utf8": "^4.2.0", + "@smithy/uuid": "^1.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.5.tgz", + "integrity": "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.5.tgz", + "integrity": "sha512-Ogt4Zi9hEbIP17oQMd68qYOHUzmH47UkK7q7Gl55iIm9oKt27MUGrC5JfpMroeHjdkOliOA4Qt3NQ1xMq/nrlA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.9.0", + "@smithy/util-hex-encoding": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-browser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.5.tgz", + "integrity": "sha512-HohfmCQZjppVnKX2PnXlf47CW3j92Ki6T/vkAT2DhBR47e89pen3s4fIa7otGTtrVxmj7q+IhH0RnC5kpR8wtw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.5.tgz", + "integrity": "sha512-ibjQjM7wEXtECiT6my1xfiMH9IcEczMOS6xiCQXoUIYSj5b1CpBbJ3VYbdwDy8Vcg5JHN7eFpOCGk8nyZAltNQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-node": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.5.tgz", + "integrity": "sha512-+elOuaYx6F2H6x1/5BQP5ugv12nfJl66GhxON8+dWVUEDJ9jah/A0tayVdkLRP0AeSac0inYkDz5qBFKfVp2Gg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.5.tgz", + "integrity": "sha512-G9WSqbST45bmIFaeNuP/EnC19Rhp54CcVdX9PDL1zyEB514WsDVXhlyihKlGXnRycmHNmVv88Bvvt4EYxWef/Q==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-codec": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.6.tgz", + "integrity": "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.5", + "@smithy/querystring-builder": "^4.2.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-blob-browser": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.2.6.tgz", + "integrity": "sha512-8P//tA8DVPk+3XURk2rwcKgYwFvwGwmJH/wJqQiSKwXZtf/LiZK+hbUZmPj/9KzM+OVSwe4o85KTp5x9DUZTjw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/chunked-blob-reader": "^5.2.0", + "@smithy/chunked-blob-reader-native": "^4.2.1", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-node": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.5.tgz", + "integrity": "sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-stream-node": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.2.5.tgz", + "integrity": "sha512-6+do24VnEyvWcGdHXomlpd0m8bfZePpUKBy7m311n+JuRwug8J4dCanJdTymx//8mi0nlkflZBvJe+dEO/O12Q==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.5.tgz", + "integrity": "sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.0.tgz", + "integrity": "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/md5-js": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.2.5.tgz", + "integrity": "sha512-Bt6jpSTMWfjCtC0s79gZ/WZ1w90grfmopVOWqkI2ovhjpD5Q2XRXuecIPB9689L2+cCySMbaXDhBPU56FKNDNg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.5.tgz", + "integrity": "sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "4.3.11", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.3.11.tgz", + "integrity": "sha512-eJXq9VJzEer1W7EQh3HY2PDJdEcEUnv6sKuNt4eVjyeNWcQFS4KmnY+CKkYOIR6tSqarn6bjjCqg1UB+8UJiPQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.18.4", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-middleware": "^4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "4.4.11", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.11.tgz", + "integrity": "sha512-EL5OQHvFOKneJVRgzRW4lU7yidSwp/vRJOe542bHgExN3KNThr1rlg0iE4k4SnA+ohC+qlUxoK+smKeAYPzfAQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/service-error-classification": "^4.2.5", + "@smithy/smithy-client": "^4.9.7", + "@smithy/types": "^4.9.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/uuid": "^1.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.6.tgz", + "integrity": "sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.5.tgz", + "integrity": "sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.5.tgz", + "integrity": "sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.5.tgz", + "integrity": "sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/querystring-builder": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.5.tgz", + "integrity": "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.5.tgz", + "integrity": "sha512-RlaL+sA0LNMp03bf7XPbFmT5gN+w3besXSWMkA8rcmxLSVfiEXElQi4O2IWwPfxzcHkxqrwBFMbngB8yx/RvaQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.5.tgz", + "integrity": "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "@smithy/util-uri-escape": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.5.tgz", + "integrity": "sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.5.tgz", + "integrity": "sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.0.tgz", + "integrity": "sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.5.tgz", + "integrity": "sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.2.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-hex-encoding": "^4.2.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-uri-escape": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "4.9.7", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.9.7.tgz", + "integrity": "sha512-pskaE4kg0P9xNQWihfqlTMyxyFR3CH6Sr6keHYghgyqqDXzjl2QJg5lAzuVe/LzZiOzcbcVtxKYi1/fZPt/3DA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.18.4", + "@smithy/middleware-endpoint": "^4.3.11", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-stream": "^4.5.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.9.0.tgz", + "integrity": "sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.5.tgz", + "integrity": "sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/querystring-parser": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-base64": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.0.tgz", + "integrity": "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.0.tgz", + "integrity": "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.1.tgz", + "integrity": "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.0.tgz", + "integrity": "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.0.tgz", + "integrity": "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.10.tgz", + "integrity": "sha512-3iA3JVO1VLrP21FsZZpMCeF93aqP3uIOMvymAT3qHIJz2YlgDeRvNUspFwCNqd/j3qqILQJGtsVQnJZICh/9YA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^4.2.5", + "@smithy/smithy-client": "^4.9.7", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "4.2.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.13.tgz", + "integrity": "sha512-PTc6IpnpSGASuzZAgyUtaVfOFpU0jBD2mcGwrgDuHf7PlFgt5TIPxCYBDbFQs06jxgeV3kd/d/sok1pzV0nJRg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/config-resolver": "^4.4.3", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/smithy-client": "^4.9.7", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-endpoints": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.5.tgz", + "integrity": "sha512-3O63AAWu2cSNQZp+ayl9I3NapW1p1rR5mlVHcF6hAB1dPZUQFfRPYtplWX/3xrzWthPGj5FqB12taJJCfH6s8A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.0.tgz", + "integrity": "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.5.tgz", + "integrity": "sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.5.tgz", + "integrity": "sha512-GBj3+EZBbN4NAqJ/7pAhsXdfzdlznOh8PydUijy6FpNIMnHPSMO2/rP4HKu+UFeikJxShERk528oy7GT79YiJg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/service-error-classification": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.6.tgz", + "integrity": "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-hex-encoding": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.0.tgz", + "integrity": "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", + "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-waiter": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.5.tgz", + "integrity": "sha512-Dbun99A3InifQdIrsXZ+QLcC0PGBPAdrl4cj1mTgJvyc9N2zf7QSxg8TBkzsCmGJdE3TLbO9ycwpY0EkWahQ/g==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/uuid": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.0.tgz", + "integrity": "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "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.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-/oJGukuH3D2+D+3H4JWLaAsJ/ji86dhRidzZ/Od7H/i8g+aCmvkeCc6Ni/f9uxGLSQVCRZkX2/lqEFG2BvWtlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie-parser": { + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.9.tgz", + "integrity": "sha512-tGZiZ2Gtc4m3wIdLkZ8mkj1T6CEHb35+VApbL2T14Dew8HA7c+04dmKqsKRNC+8RJPm16JEK0tFSwdZqubfc4g==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz", + "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", + "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", + "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^30.0.0", + "pretty-format": "^30.0.0" + } + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/multer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz", + "integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/node": { + "version": "24.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz", + "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~7.10.0" + } + }, + "node_modules/@types/passport": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", + "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/passport-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-Y0Ykz6nWP4jpxgEUYq8NoVZeCQPo1ZndJLfapI249g1jHChvRfZRO/LS3tqu26YgAS/laI1qx98sYGz0IalRXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/jsonwebtoken": "*", + "@types/passport-strategy": "*" + } + }, + "node_modules/@types/passport-local": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.38.tgz", + "integrity": "sha512-nsrW4A963lYE7lNTv9cr5WmiUD1ibYJvWrpE13oxApFsRt77b0RdtZvKbCdNIY4v/QZ6TRQWaDDEwV1kCTmcXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-strategy": "*" + } + }, + "node_modules/@types/passport-strategy": { + "version": "0.2.38", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", + "integrity": "sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", + "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.8", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", + "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/strip-json-comments": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", + "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.34", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.34.tgz", + "integrity": "sha512-KExbHVa92aJpw9WDQvzBaGVE2/Pz+pLZQloT2hjL8IqsZnV62rlPOYvNnLmf/L2dyllfVUOVBj64M0z/46eR2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "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, + "license": "ISC", + "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==", + "license": "MIT" + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz", + "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "workspaces": [ + "test/babel-8" + ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.2.0.tgz", + "integrity": "sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/babel__core": "^7.20.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.2.0.tgz", + "integrity": "sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "babel-plugin-jest-hoist": "30.2.0", + "babel-preset-current-node-syntax": "^1.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0 || ^8.0.0-beta.1" + } + }, + "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, + "license": "MIT" + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.23", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.23.tgz", + "integrity": "sha512-616V5YX4bepJFzNyOfce5Fa8fDJMfoxzOIzDCZwaGL8MKVpFrXqfNUoIpRn9YMI5pXf/VKgzjB4htFMsFKKdiQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.0", + "node-gyp-build": "^4.8.4" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/bowser": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.12.1.tgz", + "integrity": "sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.27.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz", + "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", + "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" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.8.19", + "caniuse-lite": "^1.0.30001751", + "electron-to-chromium": "^1.5.238", + "node-releases": "^2.0.26", + "update-browserslist-db": "^1.1.4" + }, + "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, + "license": "MIT", + "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, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "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==", + "license": "BSD-3-Clause" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/c12": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", + "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.3", + "confbox": "^0.2.2", + "defu": "^6.1.4", + "dotenv": "^16.6.1", + "exsolve": "^1.0.7", + "giget": "^2.0.0", + "jiti": "^2.4.2", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^1.0.0", + "pkg-types": "^2.2.0", + "rc9": "^2.1.2" }, "peerDependencies": { - "prisma": "*", - "typescript": ">=5.1.0" + "magicast": "^0.3.5" }, "peerDependenciesMeta": { - "prisma": { - "optional": true - }, - "typescript": { + "magicast": { "optional": true } } }, - "node_modules/@prisma/config": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.15.0.tgz", - "integrity": "sha512-KMEoec9b2u6zX0EbSEx/dRpx1oNLjqJEBZYyK0S3TTIbZ7GEGoVyGyFRk4C72+A38cuPLbfQGQvgOD+gBErKlA==", + "node_modules/c12/node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", "devOptional": true, - "license": "Apache-2.0", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", "dependencies": { - "c12": "3.1.0", - "deepmerge-ts": "7.1.5", - "effect": "3.16.12", - "empathic": "2.0.0" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/@prisma/debug": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.15.0.tgz", - "integrity": "sha512-y7cSeLuQmyt+A3hstAs6tsuAiVXSnw9T55ra77z0nbNkA8Lcq9rNcQg6PI00by/+WnE/aMRJ/W7sZWn2cgIy1g==", - "devOptional": true, - "license": "Apache-2.0" + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/@prisma/engines": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.15.0.tgz", - "integrity": "sha512-opITiR5ddFJ1N2iqa7mkRlohCZqVSsHhRcc29QXeldMljOf4FSellLT0J5goVb64EzRTKcIDeIsJBgmilNcKxA==", - "devOptional": true, - "hasInstallScript": true, - "license": "Apache-2.0", + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001753", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001753.tgz", + "integrity": "sha512-Bj5H35MD/ebaOV4iDLqPEtiliTN29qkGtEHCwawWn4cYm+bPJM2NsaP30vtZcnERClMzp52J4+aw2UNbK4o+zw==", + "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" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", "dependencies": { - "@prisma/debug": "6.15.0", - "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", - "@prisma/fetch-engine": "6.15.0", - "@prisma/get-platform": "6.15.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@prisma/engines-version": { - "version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb.tgz", - "integrity": "sha512-a/46aK5j6L3ePwilZYEgYDPrhBQ/n4gYjLxT5YncUTJJNRnTCVjPF86QdzUOLRdYjCLfhtZp9aum90W0J+trrg==", - "devOptional": true, - "license": "Apache-2.0" + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } }, - "node_modules/@prisma/fetch-engine": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.15.0.tgz", - "integrity": "sha512-xcT5f6b+OWBq6vTUnRCc7qL+Im570CtwvgSj+0MTSGA1o9UDSKZ/WANvwtiRXdbYWECpyC3CukoG3A04VTAPHw==", + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "devOptional": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@prisma/debug": "6.15.0", - "@prisma/engines-version": "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb", - "@prisma/get-platform": "6.15.0" + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@prisma/get-platform": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.15.0.tgz", - "integrity": "sha512-Jbb+Xbxyp05NSR1x2epabetHiXvpO8tdN2YNoWoA/ZsbYyxxu/CO/ROBauIFuMXs3Ti+W7N7SJtWsHGaWte9Rg==", + "node_modules/ci-info": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", "devOptional": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@prisma/debug": "6.15.0" + "consola": "^3.2.3" } }, - "node_modules/@sinclair/typebox": { - "version": "0.34.41", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", - "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==", + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", "dev": true, "license": "MIT" }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "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, - "license": "BSD-3-Clause", + "license": "ISC", "dependencies": { - "type-detect": "4.0.8" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1" + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" } }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", - "license": "MIT" - }, - "node_modules/@standard-schema/spec": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", - "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", "dev": true, "license": "MIT" }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "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==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } }, - "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==", + "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==", "dev": true, "license": "MIT" }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "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, "license": "MIT" }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", - "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", - "dev": true, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], "license": "MIT", - "optional": true, "dependencies": { - "tslib": "^2.4.0" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" } }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "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, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", "license": "MIT", "dependencies": { - "@babel/types": "^7.0.0" + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, + "node_modules/cookie-parser/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "engines": { + "node": ">=6.6.0" } }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", - "dev": true, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "license": "MIT", "dependencies": { - "@babel/types": "^7.28.2" + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" } }, - "node_modules/@types/bcrypt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-6.0.0.tgz", - "integrity": "sha512-/oJGukuH3D2+D+3H4JWLaAsJ/ji86dhRidzZ/Od7H/i8g+aCmvkeCc6Ni/f9uxGLSQVCRZkX2/lqEFG2BvWtlQ==", + "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, "license": "MIT", "dependencies": { - "@types/node": "*" + "@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/@types/body-parser": { - "version": "1.19.6", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", - "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "node_modules/create-jest/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, "license": "MIT", "dependencies": { - "@types/connect": "*", - "@types/node": "*" + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "node_modules/create-jest/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, "license": "MIT", "dependencies": { - "@types/node": "*" + "@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/@types/cookie-parser": { - "version": "1.4.9", - "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.9.tgz", - "integrity": "sha512-tGZiZ2Gtc4m3wIdLkZ8mkj1T6CEHb35+VApbL2T14Dew8HA7c+04dmKqsKRNC+8RJPm16JEK0tFSwdZqubfc4g==", + "node_modules/create-jest/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, - "license": "MIT", - "peerDependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/cors": { - "version": "2.8.19", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", - "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } + "license": "MIT" }, - "node_modules/@types/express": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz", - "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==", + "node_modules/create-jest/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" + } + ], "license": "MIT", - "peer": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^5.0.0", - "@types/serve-static": "*" + "engines": { + "node": ">=8" } }, - "node_modules/@types/express-serve-static-core": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", - "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", + "node_modules/create-jest/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, "license": "MIT", "dependencies": { + "@jest/types": "^29.6.3", "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" + "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/@types/http-errors": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", - "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "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, "license": "MIT" }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { - "@types/istanbul-lib-coverage": "*" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "dev": true, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "license": "MIT", "dependencies": { - "@types/istanbul-lib-report": "*" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@types/jest": { - "version": "30.0.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", - "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", + "node_modules/dedent": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", + "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", "dev": true, "license": "MIT", - "dependencies": { - "expect": "^30.0.0", - "pretty-format": "^30.0.0" + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } } }, - "node_modules/@types/jsonwebtoken": { - "version": "9.0.10", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", - "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, "license": "MIT", - "dependencies": { - "@types/ms": "*", - "@types/node": "*" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true, - "license": "MIT" + "node_modules/deepmerge-ts": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", + "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=16.0.0" + } }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "dev": true, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "devOptional": true, "license": "MIT" }, - "node_modules/@types/multer": { + "node_modules/depd": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz", - "integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/node": { - "version": "24.3.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz", - "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==", - "license": "MIT", - "peer": true, - "dependencies": { - "undici-types": "~7.10.0" - } - }, - "node_modules/@types/passport": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", - "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==", - "dev": true, + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "license": "MIT", - "dependencies": { - "@types/express": "*" + "engines": { + "node": ">= 0.8" } }, - "node_modules/@types/passport-jwt": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-4.0.1.tgz", - "integrity": "sha512-Y0Ykz6nWP4jpxgEUYq8NoVZeCQPo1ZndJLfapI249g1jHChvRfZRO/LS3tqu26YgAS/laI1qx98sYGz0IalRXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/jsonwebtoken": "*", - "@types/passport-strategy": "*" - } + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "devOptional": true, + "license": "MIT" }, - "node_modules/@types/passport-local": { - "version": "1.0.38", - "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.38.tgz", - "integrity": "sha512-nsrW4A963lYE7lNTv9cr5WmiUD1ibYJvWrpE13oxApFsRt77b0RdtZvKbCdNIY4v/QZ6TRQWaDDEwV1kCTmcXg==", + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, "license": "MIT", - "dependencies": { - "@types/express": "*", - "@types/passport": "*", - "@types/passport-strategy": "*" + "engines": { + "node": ">=8" } }, - "node_modules/@types/passport-strategy": { - "version": "0.2.38", - "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", - "integrity": "sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==", + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*", - "@types/passport": "*" + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" } }, - "node_modules/@types/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "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, - "license": "MIT" + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true, - "license": "MIT" + "node_modules/dotenv": { + "version": "17.2.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", + "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } }, - "node_modules/@types/send": { - "version": "0.17.5", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", - "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", - "dev": true, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/@types/serve-static": { - "version": "1.15.8", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", - "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", + "node_modules/dynamic-dedupe": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", + "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" + "xtend": "^4.0.0" } }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", - "dev": true, - "license": "MIT" + "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==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } }, - "node_modules/@types/strip-json-comments": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", - "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", - "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==", "license": "MIT" }, - "node_modules/@types/yargs": { - "version": "17.0.34", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.34.tgz", - "integrity": "sha512-KExbHVa92aJpw9WDQvzBaGVE2/Pz+pLZQloT2hjL8IqsZnV62rlPOYvNnLmf/L2dyllfVUOVBj64M0z/46eR2A==", - "dev": true, + "node_modules/effect": { + "version": "3.16.12", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.16.12.tgz", + "integrity": "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==", + "devOptional": true, "license": "MIT", "dependencies": { - "@types/yargs-parser": "*" + "@standard-schema/spec": "^1.0.0", + "fast-check": "^3.23.1" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "node_modules/electron-to-chromium": { + "version": "1.5.244", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.244.tgz", + "integrity": "sha512-OszpBN7xZX4vWMPJwB9illkN/znA8M36GQqQxi6MNy9axWxhOfJyZZJtSLQCpEFLHP2xK33BiWx9aIuIEXVCcw==", "dev": true, "license": "ISC" }, - "node_modules/@unrs/resolver-binding-android-arm-eabi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", - "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", - "cpu": [ - "arm" - ], + "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, "license": "MIT", - "optional": true, - "os": [ - "android" - ] + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } }, - "node_modules/@unrs/resolver-binding-android-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", - "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", - "cpu": [ - "arm64" - ], + "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, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] + "license": "MIT" }, - "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", - "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] + "engines": { + "node": ">=14" + } }, - "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", - "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] + "engines": { + "node": ">= 0.8" + } }, - "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", - "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/engine.io": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", + "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] + "dependencies": { + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.7.2", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1" + }, + "engines": { + "node": ">=10.2.0" + } }, - "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", - "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", - "cpu": [ - "arm" - ], - "dev": true, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": ">=10.0.0" + } }, - "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", - "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", - "cpu": [ - "arm" - ], - "dev": true, + "node_modules/engine.io/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } }, - "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", - "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } }, - "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", - "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/engine.io/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": ">= 0.6" + } }, - "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", - "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", - "cpu": [ - "ppc64" - ], - "dev": true, + "node_modules/engine.io/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } }, - "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", - "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", - "cpu": [ - "riscv64" - ], - "dev": true, + "node_modules/engine.io/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": ">= 0.6" + } }, - "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", - "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", - "cpu": [ - "riscv64" - ], - "dev": true, + "node_modules/engine.io/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } }, - "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", - "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", - "cpu": [ - "s390x" - ], + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "is-arrayish": "^0.2.1" + } }, - "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", - "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": ">= 0.4" + } }, - "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", - "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": ">= 0.4" + } }, - "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", - "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", - "cpu": [ - "wasm32" - ], - "dev": true, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", - "optional": true, "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.11" + "es-errors": "^1.3.0" }, "engines": { - "node": ">=14.0.0" + "node": ">= 0.4" } }, - "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", - "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", - "cpu": [ - "arm64" - ], + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "engines": { + "node": ">=6" + } }, - "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", - "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", - "cpu": [ - "ia32" - ], + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "engines": { + "node": ">=8" + } }, - "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", - "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", - "cpu": [ - "x64" - ], + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "engines": { + "node": ">= 0.6" + } }, - "node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, "license": "MIT", "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" + "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": ">= 0.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "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, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, "engines": { - "node": ">=0.4.0" + "node": ">= 0.8.0" } }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "node_modules/expect": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", "dev": true, "license": "MIT", "dependencies": { - "acorn": "^8.11.0" + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" }, "engines": { - "node": ">=0.4.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "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, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", "license": "MIT", "dependencies": { - "type-fest": "^0.21.3" + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" }, "engines": { - "node": ">=8" + "node": ">= 18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "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, + "node_modules/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/fast-check": { + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", + "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], "license": "MIT", + "dependencies": { + "pure-rand": "^6.1.0" + }, "engines": { - "node": ">=8" + "node": ">=8.0.0" } }, - "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==", + "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, + "license": "MIT" + }, + "node_modules/fast-xml-parser": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", + "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "strnum": "^2.1.0" }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "bin": { + "fxparser": "src/cli/cli.js" } }, - "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==", + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, - "license": "ISC", + "license": "Apache-2.0", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" + "bser": "2.1.1" } }, - "node_modules/append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", - "license": "MIT" - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } }, - "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, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/babel-jest": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.2.0.tgz", - "integrity": "sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==", + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/transform": "30.2.0", - "@types/babel__core": "^7.20.5", - "babel-plugin-istanbul": "^7.0.1", - "babel-preset-jest": "30.2.0", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "slash": "^3.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.11.0 || ^8.0.0-0" + "node": ">=8" } }, - "node_modules/babel-plugin-istanbul": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz", - "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==", + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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, - "license": "BSD-3-Clause", - "workspaces": [ - "test/babel-8" + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" ], - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-instrument": "^6.0.2", - "test-exclude": "^6.0.0" - }, "engines": { - "node": ">=12" + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/babel-plugin-jest-hoist": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.2.0.tgz", - "integrity": "sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==", + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, "license": "MIT", - "dependencies": { - "@types/babel__core": "^7.20.5" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=6.9.0" } }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", - "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "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, - "license": "MIT", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" - }, - "peerDependencies": { - "@babel/core": "^7.0.0 || ^8.0.0-0" + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/babel-preset-jest": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.2.0.tgz", - "integrity": "sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==", - "dev": true, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { - "babel-plugin-jest-hoist": "30.2.0", - "babel-preset-current-node-syntax": "^1.2.0" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.11.0 || ^8.0.0-beta.1" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, - "license": "MIT" - }, - "node_modules/base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", "license": "MIT", "engines": { - "node": "^4.5.0 || >= 5.9" - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.8.23", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.23.tgz", - "integrity": "sha512-616V5YX4bepJFzNyOfce5Fa8fDJMfoxzOIzDCZwaGL8MKVpFrXqfNUoIpRn9YMI5pXf/VKgzjB4htFMsFKKdiQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" + "node": ">=8.0.0" } }, - "node_modules/bcrypt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", - "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", - "hasInstallScript": true, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "license": "MIT", "dependencies": { - "node-addon-api": "^8.3.0", - "node-gyp-build": "^4.8.4" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 18" + "node": ">= 0.4" } }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/body-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", "license": "MIT", "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.0", - "http-errors": "^2.0.0", - "iconv-lite": "^0.6.3", - "on-finished": "^2.4.1", - "qs": "^6.14.0", - "raw-body": "^3.0.0", - "type-is": "^2.0.0" + "resolve-pkg-maps": "^1.0.0" }, - "engines": { - "node": ">=18" + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, + "node_modules/giget": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", + "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "devOptional": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "citty": "^0.1.6", + "consola": "^3.4.0", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.6", + "nypm": "^0.6.0", + "pathe": "^2.0.3" + }, + "bin": { + "giget": "dist/cli.mjs" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "fill-range": "^7.1.1" + "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": ">=8" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/browserslist": { - "version": "4.27.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz", - "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", + "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, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "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, + "license": "ISC" + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "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" - } - ], "license": "MIT", - "peer": true, "dependencies": { - "baseline-browser-mapping": "^2.8.19", - "caniuse-lite": "^1.0.30001751", - "electron-to-chromium": "^1.5.238", - "node-releases": "^2.0.26", - "update-browserslist-db": "^1.1.4" + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" }, "bin": { - "browserslist": "cli.js" + "handlebars": "bin/handlebars" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" } }, - "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==", + "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==", "dev": true, "license": "MIT", - "dependencies": { - "fast-json-stable-stringify": "2.x" - }, "engines": { - "node": ">= 6" + "node": ">=8" } }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "node-int64": "^0.4.0" + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", - "license": "BSD-3-Clause" + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } }, - "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/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, "license": "MIT" }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { - "streamsearch": "^1.1.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">=10.16.0" + "node": ">= 0.8" } }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/c12": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", - "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "chokidar": "^4.0.3", - "confbox": "^0.2.2", - "defu": "^6.1.4", - "dotenv": "^16.6.1", - "exsolve": "^1.0.7", - "giget": "^2.0.0", - "jiti": "^2.4.2", - "ohash": "^2.0.11", - "pathe": "^2.0.3", - "perfect-debounce": "^1.0.0", - "pkg-types": "^2.2.0", - "rc9": "^2.1.2" - }, - "peerDependencies": { - "magicast": "^0.3.5" - }, - "peerDependenciesMeta": { - "magicast": { - "optional": true - } + "node_modules/http-status": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-status/-/http-status-2.1.0.tgz", + "integrity": "sha512-O5kPr7AW7wYd/BBiOezTwnVAnmSNFY+J7hlZD2X5IOxVBetjcHAiTXhzj0gMrnojQlwy+UT1/Y3H3vJ3UlmvLA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 0.4.0" } }, - "node_modules/c12/node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "devOptional": true, - "license": "BSD-2-Clause", + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" + "node": ">=10.17.0" } }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "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==", "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=0.10.0" } }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.8.19" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "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==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001753", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001753.tgz", - "integrity": "sha512-Bj5H35MD/ebaOV4iDLqPEtiliTN29qkGtEHCwawWn4cYm+bPJM2NsaP30vtZcnERClMzp52J4+aw2UNbK4o+zw==", - "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" - } - ], - "license": "CC-BY-4.0" + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">= 0.10" } }, - "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==", + "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, + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "devOptional": true, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, "license": "MIT", "dependencies": { - "readdirp": "^4.0.1" + "hasown": "^2.0.2" }, "engines": { - "node": ">= 14.16.0" + "node": ">= 0.4" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ci-info": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", - "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/citty": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", - "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", - "devOptional": true, + "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, "license": "MIT", - "dependencies": { - "consola": "^3.2.3" + "engines": { + "node": ">=8" } }, - "node_modules/cjs-module-lexer": { + "node_modules/is-generator-fn": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.1.0.tgz", - "integrity": "sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "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==", + "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, - "license": "ISC", + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=12" + "node": ">=0.10.0" } }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "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, "license": "MIT", "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "node": ">=0.12.0" } }, - "node_modules/collect-v8-coverage": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", - "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", - "dev": true, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, - "node_modules/color-convert": { + "node_modules/is-stream": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } }, - "node_modules/concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "engines": [ - "node >= 6.0" - ], - "license": "MIT", + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" } }, - "node_modules/confbox": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", - "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", - "devOptional": true, - "license": "MIT" + "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, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/consola": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", - "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", - "devOptional": true, - "license": "MIT", + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, "engines": { - "node": "^14.18.0 || >=16.10.0" + "node": ">=10" } }, - "node_modules/content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", - "license": "MIT", + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "safe-buffer": "5.2.1" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "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==", + "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, "license": "MIT", + "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": ">= 0.6" + "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/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==", + "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, - "license": "MIT" - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, "engines": { - "node": ">= 0.6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/cookie-parser": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", - "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "node_modules/jest-changed-files/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-changed-files/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, "license": "MIT", "dependencies": { - "cookie": "0.7.2", - "cookie-signature": "1.0.6" + "@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": ">= 0.8.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/cookie-parser/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/jest-changed-files/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, "license": "MIT" }, - "node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "node_modules/jest-changed-files/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" + } + ], "license": "MIT", "engines": { - "node": ">=6.6.0" + "node": ">=8" } }, - "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==", + "node_modules/jest-changed-files/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, "license": "MIT", "dependencies": { - "object-assign": "^4", - "vary": "^1" + "@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": ">= 0.10" + "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==", + "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, - "license": "MIT" + "license": "MIT", + "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/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/jest-circus/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, "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">= 8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "node_modules/jest-circus/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, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "@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": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dedent": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", - "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", + "node_modules/jest-circus/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, + "license": "MIT" + }, + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" + "engines": { + "node": ">=10" }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "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==", + "node_modules/jest-circus/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" + } + ], "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/deepmerge-ts": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", - "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", - "devOptional": true, - "license": "BSD-3-Clause", + "node_modules/jest-circus/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, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">=16.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/defu": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", - "devOptional": true, - "license": "MIT" - }, - "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==", + "node_modules/jest-circus/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, "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">= 0.8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/destr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", - "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", - "devOptional": true, - "license": "MIT" + "node_modules/jest-circus/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, + "license": "MIT", + "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/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==", + "node_modules/jest-circus/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, "license": "MIT", + "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": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "node_modules/jest-circus/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, - "license": "BSD-3-Clause", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, "engines": { - "node": ">=0.3.1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dotenv": { - "version": "17.2.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", - "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", - "license": "BSD-2-Clause", + "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, + "license": "MIT", + "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": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://dotenvx.com" + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "node_modules/jest-cli/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, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dynamic-dedupe": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", - "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", + "node_modules/jest-cli/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, "license": "MIT", "dependencies": { - "xtend": "^4.0.0" + "@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/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "node_modules/jest-cli/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, "license": "MIT" }, - "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==", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" + "node_modules/jest-cli/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/effect": { - "version": "3.16.12", - "resolved": "https://registry.npmjs.org/effect/-/effect-3.16.12.tgz", - "integrity": "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==", - "devOptional": true, + "node_modules/jest-cli/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, "license": "MIT", "dependencies": { - "@standard-schema/spec": "^1.0.0", - "fast-check": "^3.23.1" + "@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/electron-to-chromium": { - "version": "1.5.244", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.244.tgz", - "integrity": "sha512-OszpBN7xZX4vWMPJwB9illkN/znA8M36GQqQxi6MNy9axWxhOfJyZZJtSLQCpEFLHP2xK33BiWx9aIuIEXVCcw==", - "dev": true, - "license": "ISC" + "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, + "license": "MIT", + "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/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "node_modules/jest-config/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, "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "@sinclair/typebox": "^0.27.8" }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-config/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, - "license": "MIT" - }, - "node_modules/empathic": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", - "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", - "devOptional": true, "license": "MIT", + "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" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "node_modules/jest-config/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, "license": "MIT", + "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": ">= 0.8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/engine.io": { - "version": "6.6.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", - "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", + "node_modules/jest-config/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, "license": "MIT", "dependencies": { - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.7.2", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.17.1" - }, - "engines": { - "node": ">=10.2.0" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/engine.io-parser": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", - "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "node_modules/jest-config/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, + "license": "MIT" + }, + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "license": "MIT", "engines": { - "node": ">=10.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/engine.io/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==", + "node_modules/jest-config/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, "license": "MIT", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "@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": ">= 0.6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" } }, - "node_modules/engine.io/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", + "node_modules/jest-config/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "ms": "^2.1.3" + "@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": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">=8" } }, - "node_modules/engine.io/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==", + "node_modules/jest-config/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, "license": "MIT", + "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": ">= 0.6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/engine.io/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==", + "node_modules/jest-config/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, "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { - "node": ">= 0.6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/engine.io/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==", + "node_modules/jest-config/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" + } + ], "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/engine.io/node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "node_modules/jest-config/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "engines": { + "node": ">=8" } }, - "node_modules/error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "node_modules/jest-config/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, "license": "MIT", "dependencies": { - "is-arrayish": "^0.2.1" + "@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/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "node_modules/jest-config/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, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "node_modules/jest-config/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, "license": "MIT", + "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": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "node_modules/jest-config/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, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/esbuild": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", - "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", - "hasInstallScript": true, + "node_modules/jest-config/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, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.9", - "@esbuild/android-arm": "0.25.9", - "@esbuild/android-arm64": "0.25.9", - "@esbuild/android-x64": "0.25.9", - "@esbuild/darwin-arm64": "0.25.9", - "@esbuild/darwin-x64": "0.25.9", - "@esbuild/freebsd-arm64": "0.25.9", - "@esbuild/freebsd-x64": "0.25.9", - "@esbuild/linux-arm": "0.25.9", - "@esbuild/linux-arm64": "0.25.9", - "@esbuild/linux-ia32": "0.25.9", - "@esbuild/linux-loong64": "0.25.9", - "@esbuild/linux-mips64el": "0.25.9", - "@esbuild/linux-ppc64": "0.25.9", - "@esbuild/linux-riscv64": "0.25.9", - "@esbuild/linux-s390x": "0.25.9", - "@esbuild/linux-x64": "0.25.9", - "@esbuild/netbsd-arm64": "0.25.9", - "@esbuild/netbsd-x64": "0.25.9", - "@esbuild/openbsd-arm64": "0.25.9", - "@esbuild/openbsd-x64": "0.25.9", - "@esbuild/openharmony-arm64": "0.25.9", - "@esbuild/sunos-x64": "0.25.9", - "@esbuild/win32-arm64": "0.25.9", - "@esbuild/win32-ia32": "0.25.9", - "@esbuild/win32-x64": "0.25.9" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/jest-config/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/jest-config/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, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "node_modules/jest-config/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "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==", + "node_modules/jest-config/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" }, "engines": { - "node": ">=4" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "node_modules/jest-diff": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", + "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "dev": true, "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.2.0" + }, "engines": { - "node": ">= 0.6" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "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, "license": "MIT", "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" + "detect-newline": "^3.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/exit-x": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", - "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", + "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, "license": "MIT", + "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": ">= 0.8.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/expect": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", - "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", + "node_modules/jest-each/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, "license": "MIT", "dependencies": { - "@jest/expect-utils": "30.2.0", - "@jest/get-type": "30.1.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/express": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", - "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "node_modules/jest-each/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, "license": "MIT", "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.0", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" + "@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": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/exsolve": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", - "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", - "devOptional": true, + "node_modules/jest-each/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, "license": "MIT" }, - "node_modules/fast-check": { - "version": "3.23.2", - "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", - "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", - "devOptional": true, + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-each/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": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" } ], "license": "MIT", - "dependencies": { - "pure-rand": "^6.1.0" - }, "engines": { - "node": ">=8.0.0" + "node": ">=8" } }, - "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==", + "node_modules/jest-each/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, - "license": "MIT" + "license": "MIT", + "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/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "node_modules/jest-each/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, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "bser": "2.1.1" + "@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/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "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, "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" + "@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": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/finalhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", - "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "node_modules/jest-environment-node/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, "license": "MIT", "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">= 0.8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-environment-node/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, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "@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/jest-environment-node/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, + "license": "MIT" + }, + "node_modules/jest-environment-node/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" + } + ], + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "node_modules/jest-environment-node/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, - "license": "ISC", + "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=14" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node/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, + "license": "MIT", + "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" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "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, - "license": "ISC", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz", + "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.2.0", + "jest-worker": "30.2.0", + "micromatch": "^4.0.8", + "walker": "^1.0.8" + }, "engines": { - "node": ">=14" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "optionalDependencies": { + "fsevents": "^2.3.3" } }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "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, "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">= 0.6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "node_modules/jest-leak-detector/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, "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, "engines": { - "node": ">= 0.8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-leak-detector/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, - "license": "ISC" + "license": "MIT" }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, + "node_modules/jest-leak-detector/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "license": "MIT", - "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==", - "license": "MIT", + "node": ">=10" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "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==", + "node_modules/jest-leak-detector/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, "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, "engines": { - "node": ">=6.9.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.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==", + "node_modules/jest-matcher-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", + "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "jest-diff": "30.2.0", + "pretty-format": "30.2.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "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==", + "node_modules/jest-message-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", + "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.2.0", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, "engines": { - "node": ">=8.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "node_modules/jest-mock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", + "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "dev": true, "license": "MIT", "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-util": "30.2.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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==", + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=6" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/get-tsconfig": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", - "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "dev": true, "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/giget": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", - "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", - "devOptional": true, + "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, "license": "MIT", "dependencies": { - "citty": "^0.1.6", - "consola": "^3.4.0", - "defu": "^6.1.4", - "node-fetch-native": "^1.6.6", - "nypm": "^0.6.0", - "pathe": "^2.0.3" + "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" }, - "bin": { - "giget": "dist/cli.mjs" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "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, - "license": "ISC", + "license": "MIT", "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" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-resolve-dependencies/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, - "license": "ISC", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve/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, + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">= 6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "node_modules/jest-resolve/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, "license": "MIT", - "engines": { - "node": ">= 0.4" + "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" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-resolve/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, - "license": "ISC" + "license": "MIT" }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "node_modules/jest-resolve/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-resolve/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, "license": "MIT", "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" + "@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": ">=0.4.7" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "optionalDependencies": { - "uglify-js": "^3.1.4" + "fsevents": "^2.3.2" } }, - "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==", + "node_modules/jest-resolve/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, "license": "MIT", "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "node_modules/jest-resolve/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, "license": "MIT", - "engines": { - "node": ">= 0.4" + "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" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/jest-resolve/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, "license": "MIT", "dependencies": { - "function-bind": "^1.1.2" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-resolve/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, - "license": "MIT" - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "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, "license": "MIT", + "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": ">= 0.8" - } - }, - "node_modules/http-status": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-status/-/http-status-2.1.0.tgz", - "integrity": "sha512-O5kPr7AW7wYd/BBiOezTwnVAnmSNFY+J7hlZD2X5IOxVBetjcHAiTXhzj0gMrnojQlwy+UT1/Y3H3vJ3UlmvLA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 0.4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-runner/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, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "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==", "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "node_modules/jest-runner/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, "license": "MIT", "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" + "@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": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/jest-runner/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, "license": "MIT", + "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": ">=0.8.19" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "node_modules/jest-runner/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" + "node_modules/jest-runner/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, + "license": "MIT" }, - "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==", + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "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==", + "node_modules/jest-runner/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause", + "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/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==", + "node_modules/jest-runner/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" + } + ], "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "binary-extensions": "^2.0.0" + "@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/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "node_modules/jest-runner/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, "license": "MIT", "dependencies": { - "hasown": "^2.0.2" + "@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": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/jest-runner/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, "license": "MIT", + "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": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.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==", + "node_modules/jest-runner/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, "license": "MIT", "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-runner/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, "license": "MIT", + "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": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-runner/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, "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-runner/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, "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, "engines": { - "node": ">=0.12.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "license": "MIT" - }, - "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==", + "node_modules/jest-runner/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "node_modules/jest-runner/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, - "license": "ISC" + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "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, - "license": "BSD-3-Clause", + "license": "MIT", + "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": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "node_modules/jest-runtime/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, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-runtime/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, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" + "@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": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", - "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "node_modules/jest-runtime/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, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.23", - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0" + "@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": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/istanbul-lib-source-maps/node_modules/@jridgewell/trace-mapping": { + "node_modules/jest-runtime/node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", @@ -4487,658 +8835,624 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/istanbul-reports": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", - "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "node_modules/jest-runtime/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, + "license": "MIT" + }, + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "@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/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "node_modules/jest-runtime/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "BSD-3-Clause", "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "@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" }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "engines": { + "node": ">=8" } }, - "node_modules/jest": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-30.2.0.tgz", - "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", + "node_modules/jest-runtime/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, "license": "MIT", - "peer": true, "dependencies": { - "@jest/core": "30.2.0", - "@jest/types": "30.2.0", - "import-local": "^3.2.0", - "jest-cli": "30.2.0" - }, - "bin": { - "jest": "bin/jest.js" + "@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": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/jest-changed-files": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.2.0.tgz", - "integrity": "sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==", + "node_modules/jest-runtime/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, "license": "MIT", "dependencies": { - "execa": "^5.1.1", - "jest-util": "30.2.0", - "p-limit": "^3.1.0" + "@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": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-circus": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.2.0.tgz", - "integrity": "sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==", + "node_modules/jest-runtime/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, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/expect": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "chalk": "^4.1.2", - "co": "^4.6.0", - "dedent": "^1.6.0", - "is-generator-fn": "^2.1.0", - "jest-each": "30.2.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-runtime": "30.2.0", - "jest-snapshot": "30.2.0", - "jest-util": "30.2.0", - "p-limit": "^3.1.0", - "pretty-format": "30.2.0", - "pure-rand": "^7.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.6" + "jest-util": "^29.7.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-circus/node_modules/pure-rand": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", - "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", + "node_modules/jest-runtime/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, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/jest-cli": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.2.0.tgz", - "integrity": "sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==", + "node_modules/jest-runtime/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, "license": "MIT", "dependencies": { - "@jest/core": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", - "chalk": "^4.1.2", - "exit-x": "^0.2.2", - "import-local": "^3.2.0", - "jest-config": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "yargs": "^17.7.2" - }, - "bin": { - "jest": "bin/jest.js" + "@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": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-config": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.2.0.tgz", - "integrity": "sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==", + "node_modules/jest-runtime/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, "license": "MIT", "dependencies": { - "@babel/core": "^7.27.4", - "@jest/get-type": "30.1.0", - "@jest/pattern": "30.0.1", - "@jest/test-sequencer": "30.2.0", - "@jest/types": "30.2.0", - "babel-jest": "30.2.0", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "deepmerge": "^4.3.1", - "glob": "^10.3.10", - "graceful-fs": "^4.2.11", - "jest-circus": "30.2.0", - "jest-docblock": "30.2.0", - "jest-environment-node": "30.2.0", - "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-runner": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "micromatch": "^4.0.8", - "parse-json": "^5.2.0", - "pretty-format": "30.2.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { "@types/node": "*", - "esbuild-register": ">=3.4.0", - "ts-node": ">=9.0.0" + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "esbuild-register": { - "optional": true - }, - "ts-node": { - "optional": true - } + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-config/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "node_modules/jest-runtime/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, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "@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/jest-config/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "node_modules/jest-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/jest-runtime/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "has-flag": "^4.0.0" }, - "bin": { - "glob": "dist/esm/bin.mjs" + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jest-config/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/jest-runtime/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/jest-config/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, - "license": "MIT", - "engines": { - "node": ">=8" + "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, + "license": "MIT", + "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" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-diff": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", - "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "node_modules/jest-snapshot/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, "license": "MIT", "dependencies": { - "@jest/diff-sequences": "30.0.1", - "@jest/get-type": "30.1.0", - "chalk": "^4.1.2", - "pretty-format": "30.2.0" + "jest-get-type": "^29.6.3" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-docblock": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.2.0.tgz", - "integrity": "sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==", + "node_modules/jest-snapshot/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, "license": "MIT", "dependencies": { - "detect-newline": "^3.1.0" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-each": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.2.0.tgz", - "integrity": "sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==", + "node_modules/jest-snapshot/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, "license": "MIT", "dependencies": { - "@jest/get-type": "30.1.0", - "@jest/types": "30.2.0", - "chalk": "^4.1.2", - "jest-util": "30.2.0", - "pretty-format": "30.2.0" + "@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": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-environment-node": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.2.0.tgz", - "integrity": "sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==", + "node_modules/jest-snapshot/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, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/fake-timers": "30.2.0", - "@jest/types": "30.2.0", + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", "@types/node": "*", - "jest-mock": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0" + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-haste-map": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz", - "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", + "node_modules/jest-snapshot/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", - "@types/node": "*", - "anymatch": "^3.1.3", - "fb-watchman": "^2.0.2", - "graceful-fs": "^4.2.11", - "jest-regex-util": "30.0.1", - "jest-util": "30.2.0", - "jest-worker": "30.2.0", - "micromatch": "^4.0.8", - "walker": "^1.0.8" - }, + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/jest-snapshot/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, + "license": "MIT" + }, + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=10" }, - "optionalDependencies": { - "fsevents": "^2.3.3" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-leak-detector": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.2.0.tgz", - "integrity": "sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==", + "node_modules/jest-snapshot/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "@jest/get-type": "30.1.0", - "pretty-format": "30.2.0" + "@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": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=8" } }, - "node_modules/jest-matcher-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", - "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "node_modules/jest-snapshot/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" + } + ], "license": "MIT", - "dependencies": { - "@jest/get-type": "30.1.0", - "chalk": "^4.1.2", - "jest-diff": "30.2.0", - "pretty-format": "30.2.0" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=8" } }, - "node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "node_modules/jest-snapshot/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, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", - "@types/stack-utils": "^2.0.3", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.6" + "@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": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-mock": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", - "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "node_modules/jest-snapshot/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "@jest/types": "30.2.0", - "@types/node": "*", - "jest-util": "30.2.0" + "@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": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=8" } }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "node_modules/jest-snapshot/node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/jest-regex-util": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", - "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "node_modules/jest-snapshot/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, "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-resolve": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.2.0.tgz", - "integrity": "sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==", + "node_modules/jest-snapshot/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, "license": "MIT", "dependencies": { - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", - "jest-pnp-resolver": "^1.2.3", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "slash": "^3.0.0", - "unrs-resolver": "^1.7.11" + "@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": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/jest-resolve-dependencies": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.2.0.tgz", - "integrity": "sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==", + "node_modules/jest-snapshot/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, "license": "MIT", "dependencies": { - "jest-regex-util": "30.0.1", - "jest-snapshot": "30.2.0" + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runner": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.2.0.tgz", - "integrity": "sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==", + "node_modules/jest-snapshot/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, "license": "MIT", "dependencies": { - "@jest/console": "30.2.0", - "@jest/environment": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", - "@types/node": "*", - "chalk": "^4.1.2", - "emittery": "^0.13.1", - "exit-x": "^0.2.2", - "graceful-fs": "^4.2.11", - "jest-docblock": "30.2.0", - "jest-environment-node": "30.2.0", - "jest-haste-map": "30.2.0", - "jest-leak-detector": "30.2.0", - "jest-message-util": "30.2.0", - "jest-resolve": "30.2.0", - "jest-runtime": "30.2.0", - "jest-util": "30.2.0", - "jest-watcher": "30.2.0", - "jest-worker": "30.2.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" + "@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": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.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==", + "node_modules/jest-snapshot/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, "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runtime": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.2.0.tgz", - "integrity": "sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==", + "node_modules/jest-snapshot/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, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/fake-timers": "30.2.0", - "@jest/globals": "30.2.0", - "@jest/source-map": "30.0.1", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "chalk": "^4.1.2", - "cjs-module-lexer": "^2.1.0", - "collect-v8-coverage": "^1.0.2", - "glob": "^10.3.10", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-snapshot": "30.2.0", - "jest-util": "30.2.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runtime/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "node_modules/jest-snapshot/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, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/jest-runtime/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runtime/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/jest-snapshot/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, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runtime/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==", + "node_modules/jest-snapshot/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jest-snapshot": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.2.0.tgz", - "integrity": "sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==", + "node_modules/jest-snapshot/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@babel/core": "^7.27.4", - "@babel/generator": "^7.27.5", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/plugin-syntax-typescript": "^7.27.1", - "@babel/types": "^7.27.3", - "@jest/expect-utils": "30.2.0", - "@jest/get-type": "30.1.0", - "@jest/snapshot-utils": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", - "babel-preset-current-node-syntax": "^1.2.0", - "chalk": "^4.1.2", - "expect": "30.2.0", - "graceful-fs": "^4.2.11", - "jest-diff": "30.2.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-util": "30.2.0", - "pretty-format": "30.2.0", - "semver": "^7.7.2", - "synckit": "^0.11.8" + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/jest-util": { @@ -5173,21 +9487,72 @@ } }, "node_modules/jest-validate": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.2.0.tgz", - "integrity": "sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==", + "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, "license": "MIT", "dependencies": { - "@jest/get-type": "30.1.0", - "@jest/types": "30.2.0", - "camelcase": "^6.3.0", - "chalk": "^4.1.2", + "@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": "30.2.0" + "pretty-format": "^29.7.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/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, + "license": "MIT", + "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/jest-validate/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, + "license": "MIT" + }, + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/jest-validate/node_modules/camelcase": { @@ -5203,24 +9568,111 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/jest-validate/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, + "license": "MIT", + "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/jest-watcher": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.2.0.tgz", - "integrity": "sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==", + "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, "license": "MIT", "dependencies": { - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "ansi-escapes": "^4.3.2", - "chalk": "^4.1.2", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "30.2.0", - "string-length": "^4.0.2" + "jest-util": "^29.7.0", + "string-length": "^4.0.1" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watcher/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watcher/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, + "license": "MIT", + "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/jest-watcher/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, + "license": "MIT" + }, + "node_modules/jest-watcher/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" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher/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, + "license": "MIT", + "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-worker": { @@ -5229,6 +9681,7 @@ "integrity": "sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { "@types/node": "*", "@ungap/structured-clone": "^1.3.0", @@ -5246,6 +9699,7 @@ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -5256,6 +9710,44 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/jest/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, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest/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, + "license": "MIT", + "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/jest/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, + "license": "MIT" + }, "node_modules/jiti": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", @@ -5274,9 +9766,9 @@ "license": "MIT" }, "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==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, "license": "MIT", "dependencies": { @@ -5363,6 +9855,16 @@ "safe-buffer": "^5.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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -5589,16 +10091,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -5678,22 +10170,6 @@ "node": ">= 0.6" } }, - "node_modules/napi-postinstall": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", - "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", - "dev": true, - "license": "MIT", - "bin": { - "napi-postinstall": "lib/cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/napi-postinstall" - } - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5921,13 +10397,6 @@ "node": ">=6" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -6040,30 +10509,6 @@ "dev": true, "license": "MIT" }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, "node_modules/path-to-regexp": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", @@ -6202,6 +10647,20 @@ } } }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -6380,6 +10839,16 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -6593,6 +11062,13 @@ "dev": true, "license": "ISC" }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -6855,22 +11331,6 @@ "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, - "license": "MIT", - "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", @@ -6884,20 +11344,6 @@ "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, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -6928,6 +11374,18 @@ "node": ">=0.10.0" } }, + "node_modules/strnum": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz", + "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -6954,22 +11412,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/synckit": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", - "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@pkgr/core": "^0.2.9" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/synckit" - } - }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -7245,9 +11687,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD", - "optional": true + "license": "0BSD" }, "node_modules/tsx": { "version": "4.20.5", @@ -7355,41 +11795,6 @@ "node": ">= 0.8" } }, - "node_modules/unrs-resolver": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", - "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "napi-postinstall": "^0.3.0" - }, - "funding": { - "url": "https://opencollective.com/unrs-resolver" - }, - "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.11.1", - "@unrs/resolver-binding-android-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-x64": "1.11.1", - "@unrs/resolver-binding-freebsd-x64": "1.11.1", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", - "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-musl": "1.11.1", - "@unrs/resolver-binding-wasm32-wasi": "1.11.1", - "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", - "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", - "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" - } - }, "node_modules/update-browserslist-db": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", @@ -7529,25 +11934,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "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", @@ -7560,6 +11946,7 @@ "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, "license": "ISC", + "optional": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^4.0.1" @@ -7574,6 +11961,7 @@ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "license": "ISC", + "optional": true, "engines": { "node": ">=14" }, diff --git a/mission 9/package.json b/mission 9/package.json index 5b700ce87..bcece7b63 100644 --- a/mission 9/package.json +++ b/mission 9/package.json @@ -15,6 +15,7 @@ "license": "ISC", "description": "", "dependencies": { + "@aws-sdk/client-s3": "^3.933.0", "@prisma/client": "^6.13.0", "bcrypt": "^6.0.0", "cookie-parser": "^1.4.7", @@ -43,7 +44,7 @@ "@types/passport": "^1.0.17", "@types/passport-jwt": "^4.0.1", "@types/passport-local": "^1.0.38", - "jest": "^30.2.0", + "jest": "^29.7.0", "prisma": "^6.15.0", "ts-jest": "^29.4.5", "ts-node": "^10.9.2", From a5d7f9f357cfd2886a252bf82d14e7151ec9caf2 Mon Sep 17 00:00:00 2001 From: Batur-s Date: Tue, 25 Nov 2025 09:13:53 +0900 Subject: [PATCH 38/38] [feat] add picture --- .../infra/ec2/secure-group-inbound.png.png | Bin 0 -> 237576 bytes .../infra/ec2/secure-group-outbound.png.png | Bin 0 -> 240360 bytes mission 10/infra/rds/secure-group-inbound.png | Bin 0 -> 239639 bytes mission 10/infra/rds/secure-group-outbound.png | Bin 0 -> 236624 bytes mission 10/infra/s3/policy.png.png | Bin 0 -> 215856 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 mission 10/infra/ec2/secure-group-inbound.png.png create mode 100644 mission 10/infra/ec2/secure-group-outbound.png.png create mode 100644 mission 10/infra/rds/secure-group-inbound.png create mode 100644 mission 10/infra/rds/secure-group-outbound.png create mode 100644 mission 10/infra/s3/policy.png.png diff --git a/mission 10/infra/ec2/secure-group-inbound.png.png b/mission 10/infra/ec2/secure-group-inbound.png.png new file mode 100644 index 0000000000000000000000000000000000000000..c93f42f44edcee40aa8e1dee169bacfa705c4e8e GIT binary patch literal 237576 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
  • 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 z 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℞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î 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


    ixeB!-ACa8j+PY ze=2h!s=~>k!CGf|P0g~0fVL=Ur$lH z-Sl$3S4JWJ6&mS?zQSi-uALUNpfk|R5~(s+cvwcsV<*nB=D!~tp)Qpw@- z@Kc{Ji*W&c2L9>hFPxkIH2rs;5p2it>e{fv88+$AMBo|jWz?M66mR4W$9eQ~YFSZxYd)+^JfLG^(xDfUHT8H`U`fe-3?Nzk#K9Y~an{@uy zWn;4g!;LuClERZfw4}APmWSyTLGBhWtGLmR6v<;<0Y+|?NT&d4BSQ3V_qWNIY3@F- zpoT$;prKP|I$M6ejghq)CNwMs0*LB0bcT6y#m`rpd!Dx%zh{%CtU=#APh zki4qZ`D%izMp$iRsHclu{?2}srX;EGuW2I=G^m*Z#sH*S(fnR-rGz`x%PF6oe811B z{_s{yYY1vOL!VQIX)a17$FrMYkTv-$>(x^EE4hy_-Pwt6gSBz&NpDJxfpUWs&>cFv zTcmS0$8+Mg3Z@r%wl^T^VhJ&yV8Z-7P^IUIRrhsR&&e#j(}2&4(qlV6oS>ODI1GgI z_D+MjG27VY9?)X`6-nC_ye)5=4t4e9)es(W*vZtN;t zU93%df{aSU1nN?0T1Pvx>WfSxG)VLm`X&5t;RYnjKRHF^Ab+|R8%mtdZ>^nva9>NV z%{kJEv#ZNsO5Dfpn?EBC9!TlPBA}ArHg7{ouYB8@>fG2DWV#xVgqHw+>QEPRqtGWy zhgZp$o<*?!?NMmhU{7>!v@o#@ml><74ZJrM8QDikjCk$!J%%8J(+Zt*OIeK!Mi=<@~RM(AawsbykXTKfrV=YfbwBBNBp@9a>%uxg9QCXv#N`?zMww6x$&y|8|; zqP=7yVyhPQLO$vo$=wf)ZR53uSO@ss7C#2(nbUX%T%GK3ofFi}CR>uxAf&8fQ&T@> z5mao5Ni2DM3RZd^Ty9`wCFQ|608+4CO1VG&xP5EZFnMZVvMzaP(9q(LQuD^{sWo(H z0BQ14FTIGiPN*r!N4QjrwTm=6o|>BHEtJrwKAGvDx^W!Qx8LxFruEieDfYVJjJ0qc6C*=6#im&w7z3vc|^m3i3L zWjXxt;()T@Yo-5maZ#7~=5$5H83zhFZHuxu& zmOV^&z9%=%be?AITfe&lx{&c(;=%Bnt+05c4)S|UuI}hX4Z(zS>x(X*ErT;*<$gM} zvf`*;4H(tQCd+DT1Rgm#&v2m@xWTQy56Ka>J9FnBwCeXB#U z=dH&m!T~ab+c9&%HU)e`v3vA6gEzlLs|~MM#PG1iqKD!MB74*dkkf!92qojAYc%$_ zM&l7Rl2k$HkxVMiiv#F3j-^se4m-g9{Z8 zm!IBDoOT$?7oIk8gfFlU=q>LInryqHYl5ra&*lq1YLGZ6h1G#AY{4x7zq63@JMz;d zWk6d9*(GgPHf=Xm;tSc1KH%X=2Z}Nb+26a&OjcsPgoWh+$viXO)`aG@?eu>dLZ0Ht zTQ6BFlw^Lh%3@fFqy6;=ji-(##NU4P<+UtEi_RFfuL&A;eqVN@wD;FaMzU!hb*K%x ztqO%(%ga1hCzH)+AG|B>!Hn|eeJA%!jP(;+2$IRu^;ZtDGy{WIyJcSN@;m=qc|MMH zGfA87(HiW482YkRbWEHXPw^Wvos-~EPPDm%085z9O4@5tk+A-zhB(t((d3q_ER=DX zC77A}6L$HpG>$ByW8QlYd`~ZONyh*iY_HH9V$7V2SYOHQh9C|$kt|R(W0Hc!Eom4V zLBdm0(!-NZL>M{r>y`dVQ_w&4lBYG75mCK=KA8^>Uo|dglhfW&#T3LRf^_$nizQK* zDTqZEJRLLiP?M(CaaR0yleZj&QM?@mQ^1GI3o?8FdoQnFD{S=B#8^2%Vd-paVy79% zNYf24hDa`I!zG;^G7>G_v-ksxUV^-)XBPTT=a9BJ4$q#q)*?a9Gve?_qn;o&^*e$d z)Kb&pOBVI7Ie0^=1bm4MD!vW1GlmCCTh}Z&HWb7l_OTN+<#^ax!8EAwr#n|W!pt~+8@qeGd1S4u5aZW-7iq8Vp8p;iW~-Rn!;=dHU(bzrY7qpapvx=UT>B=lp%1Ic@H@taJ%K7*yL1 zrg{1-E?X4B*+tX<#dVo0zmIiwUitI$rE+pDB61v1x;^i;d^!qHNk!Jlgt8@ZOGBN= zwLzD~a6Y@**T>19=oRs)5{E~cCBluLFXvWU>MN1ruDLWKDG5`jdW1EP>;F>=^Y$Ll zY7s2zbNWwrY%gdq$<6FRz!noxM7aUnnw67M=4JQ+0a%yEdw+a`ynlD!Rvk0QK#abQ z!(A|>N}dr6LnVG(XLKrcpU1hKJM15)7?ft8)IO2}?J4jwV<;_lGOT|4t4O}x6`O;+%L$6_58 z>*wm~dIr>8Dk|3h%28G{tox=rw6pO0v&7D3V3=}fTcDlxqHksOS+lpYs_lACf)d(R z`thYBt||O-Nt#y~{Ac!RgG6@(!|>V4i}kEUol_d~cukdcLnTsaWNNZd zK!VN3BAe7xQ!2I{Pv`B~Yiqz;2{doq>-sS2l2dsCvrUrDy$bU$`w^SQCqf&MD??j3 z_17;FUTcW+COhn?zk3x&h=AOG0W#q~4thQ8msdU?v|UF<6|N1^Eqnq@$A3;JU(Un2 z_)jNl1flPskAmG=f?!ABg)8xK5f39BDqb8MSk>*XwYmCxdjaV)&;&sn*P`-`296zH z&FqS^ENR}bEKu1S<7;;X*zWrMlmO#UeKWM;k>z%&d%h>CaCdH%F^?x8Y#5*HDSf6n zTLt!*|3)C0U;og=kJYo|Te*i70iCTlvJBSuP?0thDRmKZwr>nno!D9`^1G;8uoEl( zl34Z_Xw8l}TrKQD!CCwD<|9ez;?0>BG$?^X3Gd&P(9th2u?I*m!B1Ox{9@D@?UUJt z8vKB*Y_u_v9pUTHAXqAkIzI9`EIF@o=H#(kg?IP&GxP0{C-SnzrlbI8Kdklj^~)Hl z&ve=0KymH!t*Pn)6By%dx`v_rXgUD-lWW}E0M~NLUz~&L9BC-CXjZ;j!8QqMfRIYV zdpo+=ZD!_sQ_1`m(`LOb{!Z5fm}6aFp7(cJq~b``Jg&7So>cgq@o;q}^U|M2Uaoao zfFwNOwM8NI0}&9!jiJgnZAx-m=b(&Q(#6_$1WVgbJyKE)DZ7zEMoE=>mOlE`)=an< z#hoA*!H0x-H7)%~7ktN8bf5IQGc+}ig|6plTaK25-!)^a z8CgbA>I@#}rd!M~_j62)*ciAy$2Crb>dk+a2Vmu#adUio!+Go`$e=_1&f&V+d9zGx z=0HRmD+@tjDEZH5`TWc2iankp-IBPoxkWOta8WRyDCH@PNKvo5~&Or%m!C`K6lZGco@#^TipF0sK=MLfrasS^d~GI zvaY(?`zY@W^&<7YGBC{x2&A#oD24>O^|2dCWI)=T+qt3QHYi zjdkaweZ-o`VLoO|wsm;|@=&Nll$~E+;*N7n^S)v?;qmek%<;ddnejhKgKPb@axIH%f{^L_ z7K7(1CVg?zH4Zi*Fbg#W>c%Cov#Wc1XUsA*R!u{RRE=@g`@A}lXw@QxPWNRA8A0Hd zgzK_3sEP?MRcizzvdJVUNE$+wdN6YmIO4=Ai<`KU)O0 zBc^_DJ#_M8TvrKsbqgpyV6yH@c%q>>;gxLp0qF%RaQ^(da$k$hzE8Ij-E` zueK>Hg9-p-Gz~?1v3-HPJt}Jc<*T=UbYp;*V}6Q|9lu5Q)m^~sd?XL~=jsX+IqyGx z>1J9DVfwL#f|Y)R{k3@Phve&3vR+=CtN?$H_`AwpLymp%0rNhg7|@I&+dVia?5O>m|I4L~$h7B_2?RG_J9cX1x8I|)sa)VRru)Pl(KgXxlm zRx<2cZaN2D+O@npQZJY>YmWTOmNSe6E~ucaEbv#$yp<>@(CO~$6A(rTx`GcBRGZE0 zOI(?2U+!f%3A=QzQwxi+#Fvgc&UZ;&IE**bumc^uPgw6Gl#wD-dTD+NgEAAH&1Ze& z-2&!ImBUC%t}66(qX#$016u~IMR{i|FW+w;r&u5{Xcw;7wwqq*<87IbRX=g*;n0Bk zEK?`$E)PbIPg9AXwrd}=pyzGJ5_~qVC$87z_=6uTfkFmFYSJH!AOq4?Fc`p`#{(vg!OF+h zv$L~Q+=@yYWCuxe``Hq_cE5ilU?Dm0>SK|eET{(OM3{vCD=(lxg@WHH)h%=YY-ACL>JvKdT*nDTYmR<-_P^B&-dr|&T(MOD0}a<_FC6^?k#4Nq@%Wa8P9=_joA(MSB%o4qSlmAm$&hp2m|Exw=Y4ug*V$7 zfuw}d{TzUSgBeVmUR<2oVof*cq8m25G(B&g-r$l>CX6f?r<{e|u-d!W7>!#3Hq}V_a-TH_pRZqF8UxkF zSg-XzX25qVZZy%|SWcEStsqn6#rf@aCATKn!VC2ob;(9+#OX-)p3_WDxq+)8bAiY~ z(N;a2h62-jex&E(%?k}pi?@K;#MRB^-WXu4*b{VJ|NT0o=e}y823tvX4p2+_W$EM= z68XYK;y!xHD(#G2B`#V=@>Zz_&idbZPB^iuYFrO8WAUXM$oi!zUp+Y`EhZ(K26VGNr z*DpdlkTt%okN=4?LXDX&(^73hoB4nftA(UT6zW^JSdF@2REinOe9J4}>jq3)D%Bqe z)Q(^Ulmf?GN)JP;JJE2v$|QR;$?i6KJzs(`lo~QgMTIl50}LLrkvqZ*>XKsv7(Z>? zl0lFa!*@&8-o#o)q2S%RR*+xkluJYpn34RnNrXns@d3L`pXgZRm;8 z;MN}5C~+R$J~0^nk7J36CU8C}>Ve-&Kd58h%M^Bd<}c*3x%lV1{Y5K_l~uU!&0f)! zDX*~Wn@X?+4~w|=;QHDvJie+b@Z>4K>m4Fxq!ihp{qk;4l;O3tWY%}+YU5btDdZ4M zywA?(v+8Kf4?{M0p%Tr@-ARwBL?Z|+ZoYW!DDB&%z$QI!7Sb}sR&)3hD$)%a4<}xF z*0r*oVR3ETiu4Nle9eq~H&eB1R1o5L@f~^l?^`K)M7?0qj$VT#u$3;uI}NyFd;9v9 za=!nf6ujUD8GbINr#YYn0o!G+Tx>V!#S4R#u(E2<_U*vC<)M2bS)f z<4G>CMZF~%Z&1et-2sOQ36O2}Wx&1#^pwY*Dd}u6rH(J#0V+CX5@Lcd(Qi zN#liLNDVjD({DK(hnFu8kB)w+=Hc5lo$GX^k(Sc_bGHM|46UF{-zSh!3u3oj5nvHa%^39GP;Db(g#C!98ESZ{{lWWo;QF2dwj_rUQIR8V|{ivITj&Ai5 zxy@+wG$otfrjBQ3mYfP}L7H!^)+H$r-4fd=+IPH;ykU3n{*D=9;@`I*ZOv{|EqAp| zD#QHsYNFQZp17%=%mDDElcS~c9TSm&qEVs8OIY#M5Bwf(My%uMBWnbF1vB&$XP9_z!g zKbpKoCU=)5)756q{fg)K_V+M`JfNMc$zIl<{>yA8#Nx4?@}F;ll41lP5RZv5YQVQQ zQk^}F{(`6(sGHkUK3gNb9fIo9Eju7O`k_&*^LfB4_z9b0EXIYXSR62MFc+7*6!aS1 zvHgL-Wbq939t5$QNjY1CzkG1duiE_6IGd)OIzK4wFFZavn@HXbcWfY*S~>FyDgHVG zQ)1k36q*K+uTAOC&lLCi5Jg+}Oal;(`_7)bt0k6%ygc)Q-5h*5N)s^u^o)EK#tCV^ zyix6pb{2`M4~0M*xkp4WZHSihl?d^S;bRq!IRX|bLaJF1*VB32uATtJXNWJxA3`ubC@5*9s zr38BEB+iWf+|`f9%RfeK(N z$R`n!jiT2s7pI&(=(iHWZo7s1NpDO{?mc|UQx>wLk&L%EmA@yDJQ?=g4Sjubo*9Mv zz7U^%$LnAlT8hxU<)O%eYrDLz{K1V)pl_@-zhnhP8+T%*7NyLT?7+sWZla>V5;I?x z%{xdVdyNWB#&bE3Bv+j@PGNvL%WcimtczQr6!j%L*N{FJ)|lKEFCJY?^w?H1oo_FS zg?t6MY>xf-m^uLfBOo8ovzIa0jdr(^sV@CLefQSF1}1IXl80-(+YA@aW;_oEk{CBs zkC*N)%Ri5}0^^SR$D8Bnf2!ZL<)Ba)%gdB+ZGV{qj(NJ6em1`gCr_|%G^%91FGg?M z+PCK>igg`fY_;Fw<7Ko^lbAa;6F0%Lvm$zWX;!|v#`P8pl49|+C@(toWKda{7u_Ny zBYcXf);7Th`CN9SwX3UZ7*dLHY@n1qU1UB%)bfqwvtM%{W>hucO0)W?o*}TxV2Hb; zmTGrUm>Yt8xhq5h-%bvDfUhmR-|+JY@s^9cp)>lSzCzvA!M@s})@jjZkQaz^3~37D&56pg=${KI=p!fU^ge^ z9#EUDakE(3RmE?xgz)o`SijXB2+hH*D}^$Jo$mk6JohUUTe~g3NXx{3c7HKoUR104 z(9pYLnJ$6-#{at}0~w_FqL2&C=q#Z0RR?3lFzG!qA%_GjxSrE1e(x^YTt)Ac9~|Ct zI++KG*Olt;N$SeL^iD{2)0+wsR(7ps@Q`f0m+tNo8RQe84S>FEu3A z6A6=f72-n)$>W27K*?4S_ zDlEdcwAiRyN-(?2kb#XZfbJ5%+;4#f&X9AU>n$`*(4>Sq4z@Daf7T#j7Z@5BU?7RY zoqM>Y&tUz9Da`G>#8fI%+dxRp3Q`5Jp%Q_FSYW-ixqdDg+x?hl3|26dPw(d9$gtDX zl*SWBqa1cY4L$fS<+U~AYLqFR-G8ueDerw%+Kr?@2F#z0R#`m;|Kl1z`*|7R*VU2r z>o3}o{l{vm46WLF`r(T?V(ZBg_0_COz%W2gSV00CeS+0oUR z_S5Gwm0S34cZz}xV2fx1WqJktwC>oXKPEYR%RaKKJ{J2yn&N)0v!@asjk6<% zZ5X>?nKG@)>K)Dq#3~_9Ys>!vy=eId>YWbmUW4v6kN(R|QT_cY0f>TU>*7^2K@~T~ zTm60SMPqMh%BC+xwXZGvQf6tH_Jq&JhNsURJMumUvm5C#A~fi&LcPE!-nIrxCrS&y zfT~`J%Y?9ejSo}aL6mhNB9f=%>6r-ZY^YObG-0hj#trJ zyTCWLa}DWO&)z4C{7u|9e*zrFo95L_z_Y4Eul{u`!#iLhsM$%0mjl9xUmK>RJOF6^ zgIftd!FEVVf#DP-2~R-=23|i7BXDkp}Of4lkXjMvbp+T z+={+F4}Svv+_QQ_yOB0TRM(H2ycTS1n;|u}A+)@_5j0XaQ7OEIvo3;v<7O2Z{U*=& zldW5Yjv#hCvc-?vf7>xI)us!d%?%%It9QZEFPTMhqXCPwPxl|%nn2Z=L1|RfT~}`6 z42SMQ)76`c^Sx>iL1EtHs%@dV*@NdC%?Bc4gIi?$ymC`A`^SEd92l_j-azVzF+2bg zBM$%n1&3E8$k!AI6}^#QlbOrqg)OcHpXRV^-_Zwt#llLUzwrY-mOp~-fhTWxrN%p% zmF(EK<+jT1k1_?XF#W^+RM3Z_P`Jl?3yBGAsT9zEAP43#V9MN$5^^w=3H3KsAyGmz zx+Dhih3fW9m9x~_-@3mx@cD+%UL!fbT{UWZxh{&dbupifd2|(up`cuOl`QwUL8L9_ z8%T(((yB6c`nFFPqu7Drr87fw1m3l)Y34Qz`%l7QcG*E|wwU0APcUkhQ>`b@hz-T_&0RjyDkB5et+8}FlX%nm2mWGHQ+kU z?GK4~h_)Q=Bt4L>xF6-lwOVL}BC~5L0`g6!g#U%0DNxm{8h`(K9{2lT`4&{9Vr!efenitPa*@qhTOyvE=#X9h22vU2maGR1VwohybZtn3w zA1?&BIi{BD|2tZ~d$J<*ONhL6;(sFq1fJFnDlsyNM&NRCUZs49+<`G8D4}lj_PV9J zGTey@PE0|)QdaH>7P`^$^5p-Mx+8B@zr*v@Q~uWzx~KEsjzU`g4$=OvkAIN(|68wo zpaUKYhsqELJ7AdiLoSv9$h>D<-w{UR#Qc8;)H&PRlr?q>T?Yt8Ipy2ADScW1@T@~b z;vetK;4SG0tJHa{UVyQ|5JcyK{#)YMFZJwoYltIFFIw>6M^>~-nxLcTZId%$x16=N(ghKrw}d; z`z!bo>n~rOikM~$!`;e7+%57HgnF-BGeVyOKi5V>n8tG&q9&K8O=|M=c1wx;lG34g zCTw;Em_M*rdk-7Tbd7nKIr~=(|4m+-nk3%PIV`^?$G~MC0u?x$~6?@A5SXzMz_s>pTla@uJV# zogs}E;8i7d8{)F-Qz5M4=*5}Zt)c!2e7dCZQh<3~MZ{p2{a+zb4I7^`Z9ryPL?cKh`EJM zMjFR@Z@eEkrB(m^kbG?#+ZNZbFOTBX@v!3KDs|qQopr&fCkg6 zfHF1~u0)kS3LbqNvp!d80Xs z*mIsIe^5j8?)m3+i#<^Xm-dWRrxtC{W*+o^ak3--5VG+nJ1h1}mm~u>E5ec8sgcTQ zDPBvL1F&$fUi4ApkVww#!~9+c-z<3vV1=gz47yuM=w6r--rRIpju(6>FH{6F@yAb2 zU6NZGODsTB7p=!N(8hY0H>=eL`@rcOs_R`lE3ucv_4R5i0ePY`NPLU#GkPqGu!lP4 znGDV&rU}&iafzj?ZNu6$jqasRg7;d#h+k0}@Adqk6Zcduy7b=%N8a~`RVa7Is(*=U zaYs`3mE+&{FIED&5zMD%e0+BVCB3ZE*Bz-;h0+E%{t_u!6X5VR)XID=k6b^)Iv=m& zg3nIWqX<-^g8QqfhTez0nDhT>~zz9hYp z;Ju$N4WT9RShP}>1WgHz_AIt*+HrBtl7ZmHGqV!r-kJE-BI~647}qIzmEt^cU+XCI zSG&S82h1!HCcZpRws^K)(+U{d)y7i z^{^7(z;nY?LkH*C8m*t+ffroe+R^ zi+4zo2_@1|wbzqQX{5~@+gRp14rdU62pS%4D{{}SpV@*$DM;o&pPbn_ z;4~-hP|=ZkPeOm&**?E6fMRvijX!W7dyR_AHEifzxb?))f&xbWEbS0T%n6=9bbG5c@#641qshhyw~A_;halaV>v{WJ>3i(W7=9-r zb44uv_9>-nB?wFGnXoun7mBqBM$1%D^4FH%f7ljkmy?K=#YNr3l-W!U?4Z z*}CXGSD}nJ`YC@^!cnPGpsgJ>*XSI>zD7JK&+eMZ7WKQrmorKm;;HVFwvZ39f0xP& zL@3NZvJ{>WeK5HQkaO*~I`yNL$@ZA`>;IOVm zrU0ZQdSP#MonAQc_1fwq=#Zm$R}me5M4i)G^5wkvIRHjd>M$s$%h}F)AO_WR0QhQ2 zc;6VR&~oY;n4cIkxC*BDom)NLm#(u@cga4QS?*9XonM}**a=7gypg*VRxOaHEF#u2appH||)GjFuzrf#z(_X}4Xx z_1=jxN|9FV#yI$t=kFqBpPh-J<(~Ct9}H+8;!9Da{)vKIQ0LqXH19jLxjC#v<;laJ zS26BAnsH6NRSKgWaULX>o$zT*tEYa|LwQB=>+QHxT5a~pPHqdkwD+6O9=@VB(}_P( z>h~_1daVHBH*{g0Bsq_Jk`pBP{i}`MpcPuo07g(Q#ojycs`zZSWPo_%{6OoiyB1k=>I6}}6&s;KE~nWcOwr?# z`g2gpa}j4ungqc&6i}zagZt7&mT8I0iZ26PyX#K4EP@@fma9)w6;Nv|iZBHvZa#p~ zHkb-QUSay})NLs#=3$)@9Z(;A>GKdwyLvIJ7LlKTH8{{BE*;JTrvgHGpoNG5JG^e} z-r;G5dlwD3G#;a!5x-~Bk4VyqjWJmKIY9A}3pwZ;YrMV^Vh|($x)2+SePb!)8x;j! z*3EUvYb1W#IuM2ZY%2;VK1=30Lq`szcXj$pAh(%Cj0VL{=)u9~k5NIZzUG{q&;84n zBCnn&Z01L&Qq;}@xPQGC99}z|?JzF*(U=N@i+$*{Ty>$iJXLVmBe}9%L;Unm$*GgF z+-k1>o0ZPO!?SJxtYY=>{f*;fMH*Ht#m2vByIjRA_o^(Xf59n9$7EaGdj6RYp za!pI@kE6*i6xS%IJhQZ_VV@=atC=BDDwZ38&$RPv_rv!`*mTjMs`@=1E!fB~AC*%g z%Jry!l9g3CKW}ug=UiPPSo?+Zd<*K+(Jb1&IQ#o%ZTD4;7`zMk*<1UD?Q1+xM3fDI z`@`6-l@Zd+shdLZ((!5cql1Fj%8jJP?3_-7i-piJljraJ!I59T9O&}*!l5=xI|ftb z6}<=Ul|S|#HJh+I8F-?ea+BsXj0$kb6bs4pR2w@m?FJW$o}@e2t(faPP2qTCN70IN zgh>_My{Yje!rS8{*;PUaN~+j-_In8>vN<$0JSssYgb~@E*X%$?_&CC;=T5vr8?T8l z#zm@{btc;qm+?*`c-1nHYZ-)## zxQ^`InGY;!VR6dURBP-_NrxLI<|3nE_$4mAN}LueNtKRidNaTGk|(jRkIgQ~ z8BopkoNdR!nxwm21UhGz!cP3T+l#oDv=49|baEKc%oOnx|H>}d5h#7>!;lo&r=TM* zVo+Par#gFRv88ehO#(AsmOY=DVpjcqb|7(ekCA&dM`F~IzrgXEn&8v59LrVZuMT@@*5^kz^Dn)Ht2^ha@s&y-Rl6$+!+}xS%Xu3i+3ru* zB2_^^!zboyK4r0?_nL~@%?h*w+R|^>u(kG?6wD(SU)sMEBY3#l^{pJK_}TfCnmr|b zi`#<}H}`H$R-E@4aWtBa$&-4W#0_AWl?FXST>O1qrtBcO)D{M=hnCwg=-&Os%WwS6 z0YltXBocTZ`ZJ(b51$HrUtHw6=<%_=sj)wteV1BWcFU-G-z(~J&uo#7faF*mlRo}) zr6EoUzNleJU!~hvKqE$tPsLY3Cru*4MD%JAGNG-(K$Qv-cDg}5>j`qwt=K7X-*7{T z=V+>=74FkGJqZL0FP=aDb}p_nrxbuO(PSJisou`T*x%S!LZ4g1Ppg=W=dhK8suK^O z-lczN4+LaxndJR(XBl~^EcWM*U<(gSyOGW_&=Si*QF#I+w%U;cM0q6geW276LQ1Zv zkbpg6)0KJN^|ld?NK4l|!S`DcL)SZ;4|@_suA5goW72KgP%n|;_&_gBscbZMf+l#J zxEJ?o6G&+6-ZEVh;j8HL;4mgSMin$*+}#ep8@6t-V&l>|s*-Jq8A_toGKtE8ZNivl z;K8~Kx3H#J)v52W^MT5k_=B`-dP1Am$y^6uS9E7jvP|=hD_5rEY=s~zO=;%xO@6p? zCHq~TOCe|i5v+hjp9^~vwr!aV6mud^UQhc>TRYiIs0t86x9Ryh>V9;Y{nXH!tDWn* zxY=4XVZ0pvk<+PYT0gDc;?SIU9)w#`b3MB0W+A!g!q|oufWlO?&~F?^PK+oe=ZUZw zpC6`^#H zSdvk71|$y=S8ZxVkd9Sn?Oc-KuH5Wu+U8)~ehs5npiLs<4aZl9p%u@U>(lUJ?`EX_ItVP}7m`RjhZctJcM?p;W~ z`slfE)4r?~c_I&#`h{RNJ&FG0yo!Ce^|^7HshHgS=7$X5R`N8RWnmA_AEhT;KJe-j z`l+;E;|-%PyB{`24v|Vci}cfwucla|mlLiI`#QKlSnfe8`&g0DDdpOOVGo~Ied;CD zwW>x>%S`!*eRd}WeeA~x(6h~boQomDNN%0yo>0TmvS_G<@W$s-J;QPHw9L@5$L;_` z(c8mn@T~uEl_l9Qd#I|YazJKb6Z`f2X^zV^rAgLnY=c93D8kX+dP`w{rn#=xvt4ib zz{MNSjYB0_J=FnUf>xH#Pqq^&g}E97$mii#R5w(FSOdvdFUl6Knhdt`ios(s{`57|34E{^Mw~*!aYy9DT_6B4O<8`pwJ{yaj>a*_wbK#9 z5i->necgpwAyY6X&?07SYHGTod($^KxC%H^@K}v}2Ff~TO3r0r3eQbWO#^q#HLF*q z&2S&Q-1yv1y}I9nmrg9HGXv5f_D0cHdda+;NkKi8&y1U7M<%WPwnmb^UbnogO|J2H zA|-XIvAd=K!SV3uqWTi24>Y9nJg)1R@_zR-%kQV#o>#On>YbJMg zr8BZ_+x&&cn12H>7^np1L_#6-J5F0`e>z#Ivnmh!hS2`R%yROhI<{-U9 z#zK}g$!z^htkMl_9$@7iqwzWbxNQ1VL8z`OYvG#Bq2eg%Kfn)CZ=@oJ$ziy;{qBMHP=g)08w{SC2OUTySd$ZTCA8;TARB+T29U!+p zA5hTtIWJOf5N1FLcZoYb8ocI=k+6}DJh4Ri6@pIn7wxDzy>Zc{ z_tWOd!nnoi&0~=zV-~HmA17^cPi0-bWjmLoQ`K48zwlC5!sp}NJ%Y8GZA;75--2&T z6pE%@LL$1W*0W6~wi`NA9(URJDn64DKPq2|c0m?qOwReA+ox|XstwFq@WB@I z1~sKqVGxb)u^*rVIVb5G9)RdQvQE3ZUSVeUi&+}=rk?fwWcS$-&O!?^jEHh%iukIj z4ASti&pDc+2$&X^nT%IQB*>ioy1F%mgc_31Ev9|nx0K$uHJl=E3en}fP|g#n7?Jxu zYajfA?(!ML4GQmRWa%xfE7T3S5rT6gKmLKOTMz`9Rp0m7={0#Ue{YxS;TEyt!eZds zb&j2Ku}~e4V@H#bLv8?ltM0;d!Q7YyP+GI^8OIcB$nN1W04s}ryHPMC(Bit=bT1U% zr$4)Fv`@M?+0o5x~Q&&d*^>rpd*;Y#TRpY3$<0hcdYd~`fzxfsqaNjvOFDe9PS*6R7_J< zc_Zb>G8o4iu_vy6HOn{61SIYxT{o&4tM`r^dz*2lJtlbfha70&Jj(hp_47VDH6AUj zn&VI7#x%cYk-8Cf94f!FbF`7W#WvFq<#uzai1mqyhJOKj4Z7SAIE-A)689?c&()rL z3@9<33&NBXkSk(GX=qTBI-}ZIXMC$XpsjNrIr5UTC^_BS(}1pJLHE6HN!e(bot0UV z9mtHnqcb|hEPL2-T&cTmX?Y>U83nvE+`7zPOlFT5UxP5QblK8#H_ zu=h5p%qBK?bhaK1JQ(hj3{K)*XQ4uC~pa>^ce%yP*yK;e6nEd``8*ZZXe} z#LJLfp~`x2YoDLaVn0AX{LC}mXzdHebzbzxjo?Npj7w$4p9uFS&U!ta$}iW&8(w@1 zu?b(L-W)bQ7S~#~5F>{o(7nxfa|~NwRkYxOYh4~q{Nk2mF;C$xiw$u{cm$r22hvv0 z?k6{VWAYgoviU=UY&pi?D#|Q<)3iQqOA3wBP7JCv92uWmbJ5U3_Hpmc4F3YAey3i- zo&q~qFlpgIQc|}C@>b}AXL-FWDA(__TNP}E@9aq9w_Q9z(Z{QTy&me|6z|Umo9ar- zTO+g*gjXNy#)n%^F!~$sJpTG;pGtPn=}1Ejdws$qI7!?@XiMc4)<+y=^E`b%ALU<^ z5k@a1Re#f4urgO1heuSz8F81f^{F|~>)`fSYELJ0FxOEfx*mId*Kg~yw;{#%?zzE` z!k$r?x*c%*j!~6`WAGU0QHC3*bFYD{B;DhnDH-ph&Gxq#wG9V@Z8yWEx+dh=#}N4& z?=taRX-H#%7#x>`8%cTLD`!5JErF!Ize_dL;6}}UaqYnz*Gk&VLj`VWN??lg@d;JK zQTI$U+;R|}tntoy-?82q3Uu?aGPfmV3g|xPwKeSDbBC(7YB^=A zxrA&HJK@opydUqbmzN-Yi|j2o{Z5}zOK}-4vhQKW{v$J0LD~)v+|{{Trx$5*vlhhC z6}hvrP6gIJR0n{s_6L4$FR9)d&22|boA(j_@?*TIeEom`mplG!wk&Y*2V0+5b4*t> za?xy_2C1ATE8WO_-3_N7^LA0N?0qj%yhi{c2!dBM9CmH?Cz0+2Lq7Rfy%CE3P($80 zt=mG!Mc|3=JEpWhsZrbd;kd{pvTRr%Q*v}_NSuLo@RNV*Pw}xdp@(#+ERv$jKWfc9 zw9X7tGe~>KX?a>(F7uJ;8V7>GH;q#3lQtoN3L;d35cV?8bXUq!$M(+epeVA|g#wA(b+!wy37-~`l*MGET ztsM-p_zgHWxYc-54Xv*p49sUj4EVqJ0e;WNhZwFYnXrK@>~Mo;L+honuY%@e`uhP% zu8N9E#GqM1OiXB{(~`PMyw0^jqrikp0bD*4FewD56dtulzJKC(C>|pu5@08b2%XH= zurSc$iumzyD~W5Joj#Q-j-5VsXDo(q^(PbytXa%yf>D#^2j0`KqvO*IAoGh7GcWko^RCk+ex#zZ7spN&H3f`pY={imh zCt_c#wJjXxk02Tg>Z)Q_WyCn}V199gFD9e91^p>9b_PkEs8KQJHm8m}&98*lSDN>< znzx0Wez|do2v0%SRHoH89DIv=c9h_*%&r18Nz9l6@B4D=a(*=7@bBzXQT5ivBm}@; zOs8HbWn=uE+yd3}H<7zCVz}};p_e{(lV38!)Ye0<#DIc6q&w?qO2eKcboDgUU@4`_oXc0iWL=P{2<1UJ1neNE3a<UTdOIPe<*AY3{!rNW^_P#v>MI!xS9{Txk*%RgJ&urpr4gor>UWN1o zwjrw}x2vQjew+7deUiE`7k_N`GqK|mjjwV_p%U_Mpc+%5R0-ypUDq?uGZ*3h~T}P4)v3`U#2D; z@0XUS*{6AESX$1kLOz$|U@(y6bbLwA5%BeF!Q|!)yDQEN3&^uCH+cdZca*1T9l4>L zh(;V1a8Ong7%N)*&!7+-m&;#4{k5$ud8>+y+KPbY{e9lDj4*yCI_Sy>jmE6-T!^s! z3#3J%1}v>Tw@@#ldJpU;h$%37WFXwOz~$7@GlM(gO61Wx8&@9NOWkI+IBXKwBIDxj zNG!&V{n_u33MvIOUC$s@j@nhfI{KEbH1bO-_uO-5piQ?($0dS|AwlrVSvud~kPTI0 zXasjWePeB0-wH>M{R&a*YT$X=JD6Yv1-a(^e$vYdl}}jrg^%=ndPOdTMHT_rA zUgNKP($zn08jTrlsa^>VwrL+15u3?W>VYWb4j`r|PtjYh(mF7Y9?Up0KYVKjlk-mz zaa$OqxQY)Qt+nHLo;f6T8QKvXMM&z_tO#4`=s|5)mil`ieN^{RVn=$wD6bkD8BU6k z>Z<#iossQ=LJEc%d3g>;Ti+FvJEit`AO@_7r^xz8UULxjk6mBzn-n#b&TQ<8+Em_P zPE*}!bCk2?t^4QbO`lZx+Lojbg_tB@yE1?J`c;w>4FA2CsPhb^WT4nN8K%8|3d0aZ z*v!KdEet)A1*zE?mbWm0ircs6?xH%!T8+J2vGmBj8vxXt_y2nJVfUFeWnmXvm)hDr z%M%P1zG8aESWc9}LC-7NOgp{wqB}C5EIy~Rgp}AxcxHb5D>9*6Jz)nKT~xeZ*_epYm0i( z%`W_o56B`htP#ZWYIMu)cV2S}9U#_1SjGlwlUtKCT3uc`$kLKpS60T-w8%?pFA;rcp9XDgv z9)RcfY-rkWEmbc}uWKY`?eS#&WEs_iyXRx?Cz&1WKG*4%{7`&ge)yZu~P zA(4il;`U1?iRuqdmSJS%^z_jfRgn1+HP7>F4`~C4T&t|HwC~4^$(rv)nSCE4=KP(~ zMD51i**3ip{KMowT`Sl)f9pypJd}<>hL-A-OEy zE)@YfP3HINmo2B97TuQn7+xS!?&Pwag7TRc*USrP{k&{)!$rmq?^iWq+9M81c>N2v zh2y*V^S)=Tv5Cy*-q#y2Tl=k71FCf^_EW|3%P|oY95-(D_YJ2Y?ah`$z^d+^_@iC- zll)T+ekTJ3DmeRp$z%BI5_rZzt=qor%Y4q@Jk?pTKUKUpOqCfti<4^e!FvPzDOP-! z?xDr*?ikTm#5RY-43NI{hX@EEkA8Fu5#$A9rL?|pWSS+UB|^< z&DrlklCKw$Utt{y~aQKP1isu$2c1pXQt4%nAvY zo4MNfR_i=*<~bcud@P#E$Hxk9{gKJ~)2r`kw;NJDT}z z`~%SFRH9p+CnClzWt9WJtrpf<(=nX~R5 zbXUKsm^tUQ4~B*Qt}>2pJyc&K{`B6U?i|7Fc}xiHd<^7WA)IMX`MWTus0iEoV11ZF zTURf)svF%;_vY(XcIZ*b4vJ|_Ul*-n$u0nhVOqp+hwQYDG~1^qod0!*h`Hy(yT5gO z$)SDY6L`{3QrJX+3!QjX^BQ&`GKujPz8oNU@cC+w$i|hP>*KkHxh~SSx$xQ0_?Lk& z&3cKC_h+$ZwS#2?uCXdFd7Ay;t zK1DNX%^89fx!Vz6>qu@#5whOy11#;ezo0_%i)DKurIR1Jix}Qdb1J>sUR-71b?)WF zr){qcz4vlD8cEJ@qcl0Ml0%6KhLC4c(?a7p+V&puCc3+V*E>Hr+Y9wH@OLkrnLbCe zEBXZT^VC^TEOrgQv;?B(*W1W=MGq@VUk*hJcxd_y?NW;@VP)m*aIZIbOURysjV0E? z8&^CEB<1hn@GPu8Vs1o90HL1}Y^BfcpZDqt8L{;%Nr{OAC+H5;TnSy696xPq@!r zwH9L~N{uw*w3>}ce_y9&aJl`rC}rRNau+>~h>d&tY;bd5poI{^8Kr=1H1&LVl|k9l zdDcSnWJYm2R6R;IvuG$w=8dcrL(`bQ+`H%JlaztYiU1aYXHE^L%QA9%y067}lv%vB zFY)fXujqaEq?8nwVp)Dz!GF;p($bO?{U6$HTLzpG=ZaA|`615hI}nm|>zoBpG^Z)u zt@(gjE!wgBAC;^{WAdG3dv*0&LW+`W^bBX^vFe?Ch&}Wj>y3=ttWnJcX)O~m}G#4DdQ)Rkz((c9_Px+-ewPI{9T~_`Sk1k z|13#*(&tb_l$Q3FR1U>p-C7*!eR%ffG_b{WjH}de#dU!7Iue6wEA4IP0wM+PMjrd|82A*3sL~9*thYyg8wmT0>s7UPFYA0 zVBQ3==4HrWLkasyQna7lM&2HVflw~cFJ%^~i!E2QOP79F&$p);fR}RGYoOXpAlsO< zwEof-2H=bJHqn2EAlf?rC-~`|o-OD5e-jMP+5%oV`|kv>{)dYA-rtKun9`570d29)n&tQ;k_h~z&1FW08m#X0L< zD>E7!P+b0Tp&2*7O;uS`DNl*YYP>)uIYB91=x|Im3Y~YL_MeJ&6&JJI7ct*r%x*ZM zKW*_lzM3zK`9$RVr#GmWv6sj7tJ;TTM%TD&(e!xv*Cx!#^?FB1MA2KoN-JG-r<+ib zp%V9v0sI5+j1|C%9oE2q0lW+ZeXp|r)yKY|;aH7`=rNU!%18tSx~|3Ycy+22tg5&> zBJ4wgPerFA6)|rPg@LMT(yj17;97Ut;o&O~bcLS3eilW1q`z#rRKxd- zJ7UxXz7p}hV_OoXf{idjms)5iYCN`x8+V_zR|srJF%j190vkeh<3BatBcpyCPSX}% zdioRz9ydUB@)k3HSklQ68F!<&fj-vKEs}`u*5nq?9vKob@N`RgsAO*6*OLL44*apy zRY_cO>>|Rp47&Zid%kZsMxfD7`-QDxUsWE~(s;GFR5u(vzNChbU+e{!^~%4no>sh~ z-UymRzX?xjyo1 zY>t_O{f8{|GRn|+&26qaJ*O+b-g%pzzrn@^^F5R%pugkU4A7yEk&d4QX4);e|Uwk}^T_7$xc zE7r|T8Q=wB4jV{su zghA|8jC#oXQY%$G8;h7nnK;!@ZWe1%4SuVwPH#`KS5agL@Vf!0 zUX}d|hwc%#skYA+?%hg_3O?dZ;G0MdQ`10#li6kFj~MQb#%Ah4;h8gSs?y0n{nklN*!f zHp7H{Mb0Q1`hiVO&~K-nO6GDJUzR9`rCwhXd`iUYu`TDmIat+N!c@z$up39|1-z1C z`2S(-t>dEXx_5CJY3WiBL=fplQYEEBx*56~qy}lEMLH!#y1P3DknW+82FVea`Q1Fv z`+VQ`J?D4M=j=aV;B(I%YwvsSwb#1Vbul;-U>Xcm?}tq>Wb=q8C6t`Hh6HOwVkz@F zs6=s#gr;ON?VUMLaP5w{UI90%lx2CXm-)<-!_mLB;go+JU$4q(uv$f!qPPeF58m99&PJSc z{l~2`%sx9@H+yw!M(_AR-mfgdi`}6|Oryj4QOi+NDCSA#-%k4La4~S9Bq$@%_I~rIM=?J)tArT7fCrlSFFE zPeSQUm3QDry-2F*9&x4)OCs&)4vGr$a}CNA^;W~3@4HxUWH@o)XN>Tp9LT0)8iK&W zjHzdz{&yHq3lv|i@&G53l(g$*r3utqa_|y=9U4C#-Fv$l!+Xw_q4m=IR>8aeNOpW3 zL;=eX7ZtAUIcVa-J=+hR`}%aJ&QyoLl-e*)llWfov8Y~M9%N0B!Ts_3UOAHheJwwTmN6>t4cIZGD{k_qCZreo_%1OD6isfmm5b_~QnzIuMh<`4$ zfcE)lk%zcqY4PXI>f0M}fd^BWgnP=Q!Px2gMLHa(XQKm{P-%HF+=YMkU=A+6t$p!a zm`>?a=mzg4XWO;E{0movNb~9nUInG5&XPsC(Lwm!N*>lNV}-IYQw-mvfJ>R8@2TjuLm2MA_ev-01A5)9N@!wPhCT=BuZUvtSTBR*&~g<)mY zh4A0sPFPHl1o9W4a5|})XvCsAE;PNY?0k>^Bxs9d$|IFIqR`o_^@qG9T##y)UQPO6 z@AWrHb?a^KST=^83|QD!D(KK3`ovcONZ=;OhdUql+(KzKyZg@d!x!W#&)2&Ze2-1T#m1Mku2cnLVe@nOO)2Q%=lGruZUgE#JO(yxxRsPuJFF2 zR|cW(csYGq%<}q}7G#A~cYwkaE@pPubrhjx`HUsR>>1rE$@0;L^=|u8>ap<7{7`rO zS2nb00rS@!ex;nC#t&yDI?Wir1OvO0Cg+=cKF;{ymMHO>pZcT=I`v+(KDqH=HE_P; zB4P4|b%cLo_m}uX(E`Y}a=f)|0E)5~^?!JYA24}!XQj3_iQ&jH(BbD08+yq3`K+vC zWvq2NAIydVHT&@eu0bh+Ks8%^_Oq!c3hl*DZ-4T(>k0JboxEhM4II_5wHxsLqpKN$ z48}GybCn0ZN-v6H%2*F(<4!arkAGE&a8rl*VkT8~R_ky5%*5I`%ri}XkNR2v#?5$- zLRw7V8|P`OF($90jnB`CKUiKX!0>5ds_gpF^qp0`?n`eZ!!8Q5bKyRdp7Kj4RtG`zmYD!10hfPG z0@wvbUyvH>uUJJ=_m>}6C>2%@VA+xpXQ7KSa+r;Z;uT{~yIz}}j`SsZJRSRidZ5E; zA{Z1VB9|Q48TWK(MB?GewOna(6a1YVHI73S(Zy$J7@>$QyDNeOg*pGXJ&LhHB`5vGQ;s)(x9{$Xhxzf>-w+*>b0l z`Y$efdsbTQfp<^*lESca;Rfwl0*Nc5jX_wJaKH!t*4Lq05}Gxy%w9bYyDrk1d&aM~ zU$VmR1}SJDsk@WOPkZyJ9ZLhaj9Ug@f0MXz&{G;~FPk{|W{3*&jVW9?@w? z53kQC_~uZ9+N~j_;l>z363NBskEr8iPqT$LF1O@NqvrM&;vd8CxXSUISK8Aq&on7R zvhfAVU(pMs^f!fnO@1iqR4Z0sad|h~ILhk)L|FDbjHFjlv1swTZKp-}@4i|kpu1lE z$}*MPCmZL#Ns=1X+#K4d9;4Rw5QQ#U5C0OaPP{yc?qqR(KIMC_Z8bzB=A2=bvzikY ziDj1jc6`syzeM=1IxT+nsr79BQ~TrNaUP==D&v2eti%E}SY+1XtAnh2T7Dk#yQXe8 z`3$nkh>$!pnX&4(vl$$GL1+G`5hy)6kx02BcKdihT)3hR5bMp;UU*MK6p*lz&$Mz7s-KpIB>C+~!h|1Xu8F zWyNc1fLX*#Tp%05oSAY8b67pG*3E-}@_xM~E1A`kYqzX2xtIPf{FzH)l*9MVMmlCC z@E}}@mEuFFf*WD6iapBQ!&LSY>Oeo-I@-(;AADO#en)$Ggb06Koei0#Y<(}RZB;bt zx;J8)`=#_cN6_|6U|dUklG`G|xyANp+E1f27GLe8gq>GJeZd_P!q&?`j(_vA*`P7hO8l5<{^bDKN zl?!OxBMhG$i_&*&>kJK7z9JnRb0+eLIcSW{(~E|X1n5z##cCF+4G$hD^i@dL)s&2d1!mM#-@1UU3$Npvdqan&Iap6P)H5{4TubcvzJn8#>8{R?mAB$|$ zV@1qSRFV@82nz6m5v1(pmjT}8QcGp+0@i$=Ifc!$v;jgNrI3M12$V@^!V!k)TNEv`X zk)Mq%cJo4imdXY5XI|->mAlBQ~EPi5wq9g_-;7 zn7-%KlBw5?Pq}|Hb?nAQXEpRR^9+S(10t~Y6FYVTrBx-=uV!QUE4x@M_k0ntz5YRW z`BOWjR&V!)`%i`qbcTMk=BIIDUQKf$H&5-vkS{u*ZrPqGf#UWE7_|8Q+aMw%#VGD3&YB#QN#PgExu;m1%yB$`U*p0?$B`}+3a;}@{k3S-c1OibbR z!Gc$bG^cqktvuSFi5?Oo4r%qpTGa5GbHkGMWrsTK7;QPbrSFl@U#in1x{y$VxF%~n z>Ql2(qfrj4Wirisw5_y}G2PYJ_VWm2Q?Vz3bAY?NXwzyySnP&hVX?t-zMvnU{mCP6 zvX9MUv!-Z{^C>sIqibT0h50Disz|$4eU-EI>^Ew|9!;0o#wuBJ)25d^4lm#a zGS$;#QjUG{FTAgwwTdhBpFn~21@|HYveTeTEcW9$s`#|;Jbhx|!yJ(CH$Q@@(NVJ( ztaa>%CkB#mxEQvfpW^v&Xoaq#oWuH$)CepCs`iN`B5H1CSXa<4 zz$A_bQ383(PkmePzb}Q+G*AmWy0p=lo2{@Wl^e?6q_H_cU*55ft4<-eI_|bL?yszS zA<@L9u9grBQ#+_jzRErq)~>U`8(?`)8f?)f%{ke@Q@DXggX?R}-*qy|$oj)>p?lT! zvjz3i*B~I|zzN>eq)*g#AhX=u9IWVqichh`g}vT8eEb6+*$G@iUj`Xdmm__lWMcsxZb@D!Z?90G66x3aKH zo#}JjcWZVEw2r;uVfl@Q*)JORH4!X_41Cy6K10PfwqV)EnwO zlYa#D@4nEdUFz=M_2zNXc~uUNOtHvvBo#@$Id;;oncYCBJTCG7{9=6`KdD{ttJd|K z^yEUGYUb(l!=4AfO9#Wl16_Y_|NLc8m|HjMU=(idz646sgq-Yyh7{h64e`37& z{CR4(C{Yzj>a{IoG4zQAf?0 z6tJHl262Ie&DnwFrU+m;dkpF>HH=%#Qn+zzn`x~N!}9Nq)e)!M>H2XL0ToZGHkQ0> z;a>esQwjG|J9IV3xJkr46iT!TCB8a%hmmwD7TgV$`XvxQc$w@U_EvF>u<8=S0hB;SK1I`%zhiuIc|MU6F4sCQ)>MsAc3^G9*5ts-K#hb+3ajnT-ce<)j|wip4qNh|g<{lB%ajwViv zK6;6A(>7oW&oZ~ZsmO9w*Oz}em7e-VR*p<%sV)U3S2pXsb~Olu`!UF zt!f+#?o~ME1u$pJtoDi-@+}wrvPLc_UVXW=ovAe$daFAEPp&PWIoI3p2Iz2b!p6b# zS<0}yC;FtlYSLB4W=!Y-+dHO-zG`V3?9DX?r#6i29fNB_9Nd+AbtED8Z}6Jk528wJ*Y#;)WZ%Cx2WV*Dh=E}v zAi>u&T;=ri8#%1GhAm-qEXMD8xh!<#=pKT+cP2!y8~q8Ewc5X&V~N`{2rVSY{L$)o z^_YI!)gB}#`2z)@4WfRFY;22O&wTv%qn5ITGRGwlX zEg7PNG`@_*BROfl!eR!(9}P-)c$^(VGG-+!cx{ukNTUzhys45Typ>}OvVH8#59V}gAAYs_gt*7R7VEayEjZ&M3^Eyl5k`J zv?DH>wq`LkM?xU~=7u1urT>Wl=J!wEX>o$O{wq@s&@P3b1t638QYZj?a8VE`;DrhR zXnjrWJfd9NhLd%^v;;ZMk-*cN;KKO2*AFA%-);FBDH)Q(>}b$OR}0|Lyd1}bd99b{ z=k-wt0AbIae#S4xQ^`_tpA~!XlAHWr$d}c`67TZZD*n&_K!pF%2BTF?kc|V1vMvT% zjA%iwpJaS7I5*ylgIt;SH)g7e_r^g>5lRjF!z&UOn&;4KugU%&2cd(a3a6#fgν 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 U3?J#GGa%r&XmC}(RL|kwUvv}+R{#J2 literal 0 HcmV?d00001 diff --git a/mission 10/infra/rds/secure-group-inbound.png b/mission 10/infra/rds/secure-group-inbound.png new file mode 100644 index 0000000000000000000000000000000000000000..1564777129fbfdb1203f884f6a6524c9d9be1c02 GIT binary patch literal 239639 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%0DSfN_1KWNBon7q>FLvM!uyf%WNvA1g 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

    oJnYDdyf&O;e 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 F{{hxY6MFyv literal 0 HcmV?d00001 diff --git a/mission 10/infra/rds/secure-group-outbound.png b/mission 10/infra/rds/secure-group-outbound.png new file mode 100644 index 0000000000000000000000000000000000000000..044cd04f09dd112aa5d521bdf4bae1450f911814 GIT binary patch literal 236624 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 z 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 m%K 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 literal 0 HcmV?d00001

    Cuy5=W_zC=B8gNA(C`?GhK|7Bg;g_9IMkmJ-Uxd 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 z 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

    %<^!#xEPIgc}eH@aZqnnE7BXqV`+xKY$xkT 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 z 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

    (FX{+5i_4ec~{gnT)9R+SnZO8;|6kPkTU*e)@ z@yi5ExZE$Xh56mUH>fh{&AQ?QZA>M$7_A%nq(Nl>RJP)1gj%M-In5r$ac&7m8Zg-DE4`op-oEY@v%P^|CSc$QK`48v^!#|=AXCf1j;Uif6C$N`+q zocSvSrP4_(X2;p8tn7K5viXrcJ@h#f+w}NVof4&UwTiud|Jzrm72y#5nLy-W?M^wO+irwqp5 z?)aXG<*9Jj8HP09d47|InDEos5CcG(?O*FNcy@qOO1EDH45Q7a0^Ki2sT8*4C~lTP zOwXVs+$)vT*RigOXlsKhEKuNMQz(s`QpRA?HVX==m<`5Qm_!#3eK>Tuf4zm@?TI+v z{^Fq@CeO+y=qqLR35CoOqC^z#iEI(z{q*Ac_4lF}y4L~U=xc+~tWWTKYZC8-;%c5` zT4=}5rb+T(O{@ro-%&u4Ey`Kl9pn#ksc)G5Z5OwrByN(ZirWu@9=DA5k(_RipVoO2 zv&N%J7DQw|O*LHKcQd4+`~DC`BE)dQV(*#NKDb=mUe7eic#&W7qt^N@>6o}Rk+`Na z<4@g1sfVX-zZOFR=??H#&GN<|FS@9Rh;ng8z|il?kWp7pml?i?DqV!0!~(AW?X$xxW|t(B-O!R4&!1OeYc1(B!r?O6^+-nNOli0r8<{h$rO$De3}*pXt7WR z7)TALku7b{;z}IsXj2IePOvd=O<60?{e0V^^r2aURIM4_9!ZtD=Z#EVdC|4Ds3wy( zN7#GJQFe`mFQB+G9p2o#){0jkfrQ6*R_ob{=f}0F033@2IY5N>l*)zilcMr?bRn<< zqXSIbebLTYARY%xEf<}Ufohb*?T#Wd8* z1)e5D9;Lt%?EprP^H3rYEsa~pUq?EZLm!>&V}L_m6YjdwOR)%F(X<5^Z?Bj@nApv< z^bWw;j97QSjXm{~$P|c^i=+%B=4%SL0j$~n!kgt+ z8Yc*U(dIPFVsZy$tHvi1Wl$!!52n~^Q4)=$=ihlk`jnht1*LqH%-pR2-?V_!x004i|XMuzW8Qr;hKiX$OZVHO5>AHxVS_zl) zPgG59O<(;M)3_fL3{?s(7DP{6WR>+*TyhB{)rhMd;ZonRrnU=@V&9A^dm631Uh(vy zh1WS6k1RdHT0T(U^?JVvB69>?Gg)1FV&v)kvXt=ic`gZ?LFG@l1~7VJpUZZCXhQRC z&Dx^0)DaU(IWxaL3AIgrw}H$l)GSvR8$&@5?vakRx@GJXO| ze83|$Q_UH|@8Wav-nACElp;9|5B~DQTb$Ha805EW$9hx(sy?%?q9^;}liY_ZsZ?l% zgu={B;Z+5N=AFiwNaIq@IKw*AXPR<<;d5F zY4MOf$1}IgMD;s=tmv|n>)BdGbBteo;uN2+`||X!(Ivj=B-6RYPB^K@YgVqv8cHXJ zrR1OaIp@*6?P-DeYF-!AmiVy@dDSb0)ijrzrlAcVC?KIx@jG zwrGnEdrU!@4NYEad&YCwv~XYiIJd)#MhHipPK8iY9oy~7g58+Gx_#U7E0xDZUG!tm zbx3aZ?HRo77;yYsu1p12jEAG2IQ}p+xFB6!czj#FnC{hk=5(QiKRV(~INet{T;ieo zW!Ng3saT%fIP6RH=e^D_oV0R+^Yiom;o(A90c~N?d?XM!zG9zMg7l(KM&JqafG1+@*=vpn~?3@fbMBygnP!u92f|KSVU{?j}U{8z{V z<-bWT9mq_vbJ{Djo1E{hREzi48 z*r92zJ#ozFGh-jdXEmsR7I=-ICo-!chy!D|H+m$(2qX4Nnf|ccq$sxyf5-Oo_3ezq z7W#l@+lnTOQD=C|nxn{Np%`TT>cm*7b^q6eMW`})%xt2JlCocDLqH9k-}Xy`>pAyf zBa3^12-!MicLtJqpkPh};w5E(J2$k%8dD8v^{lsCGPerqQo6SL`pM2jKl%KNM|ua* z^{g44ptj#1XZI)asZ2o0S^FjvLE!m9p}09&pF0&&SNeM=EwX zGVu_?n2|7LBqKGC1z}>b-~~hyKg3O*$Jd>;XHZtNsVxg@crd_~o*b;ySG>@>LNeU3 zEG;dO0*jfe?rLaj8j2DHl75cV z)wmA)UrV_j9=(3knRwVK38$L(O}1A%QpkBw(7PvADfN6cOYw4Z<(E?p&)mskTV|9-#wv&c{@<>8IDZ>@4HD)m^Z@n~O^x|5jagCY^Z$wa_wSe3z0T{@LuH0~7gCn{bDETCmIzmawzyPbbIhKKiSF#YX-{97rp&QOe6w%SmmXoA_?=zHo!d43 zh@$L5&}_TQ_26H>?ZJgpl$Xw1hP>krXnLL;d;6-KyF2zh;d%f(8Z8jGX#URKn8E@L z2^HAtT?oCszv^9H$f}T&H*)M5@-D8?EDzazcpL0~M5uf7gzI!?0nK=-q*yS~v;lNr zpzS{26=m&{H=?U#{(kRq^;3o&K})@WM_IPAecihsLM01sHy1u9j2m;37UhYbgRnC%4ah+g6L^pxwPILN6(8$W(}dK%a&0-iF*%C}TT z?ce59mAe1T$1h(79?oUThrFu_=xFI9A$zU%`My(o)9DD>F`=io6?j;ej?rJ^qpSyR zv>XuEk9+dvrSY2IzogA_Zyq}tyua|-o5()7-|{zaTE^_lDKAI$(@wU~RUyDDi`nwl zm97lktj7DQ`r>|n0pItTO(#=;ryE|(`>L3>B_86>YrCy?-6I9D@rALSJH01vMcw8QM1l!IF|B?4j0nbCa39N5|CK~+kI=KF7DC+?U zExXXankY#%Xj{(VdzaYuhlR_c?KM2{_T_)ZGv^;&G3mH-ngIwrUHx3vIVCg!01$aJ AAOHXW literal 0 HcmV?d00001 diff --git a/mission 10/infra/ec2/secure-group-outbound.png.png b/mission 10/infra/ec2/secure-group-outbound.png.png new file mode 100644 index 0000000000000000000000000000000000000000..6937e5a5a4009493c770d57e5908b1eb241e4319 GIT binary patch literal 240360 zcmY(r1z41A*EKve0@8}opdv_$NOy~pDo7*UAl+TkDJWfvAl(fjsdP!Vlr%`gx955P zH~#zZKE`q8iaBHNwbowydatA)a}$Rg2Z2D`d?qWYf}tdjtZ%4f#Jxr%j$A0&$)DOj7KXi_YIv zR~J&Lv(Dxj`}=Xp_nc`1?$aiI%ewesPZVu{p&cNFLG%`dfKXeND1PR3G|QvSIv?f| z+D9(FWQ=zCwB)zY=;<+uX`RKlEh2w8jPFFPTi02*F+Aa;HT6vULM{7R-qF!*O#O#fDR3Fm$&C`frb45PKR6&oKvXwWpL9R5`oC5!R9b#)v3F)q){ z%tY~{9hms4|2aCvSa5 z82|ShxZ|vsUlc;3qOkhQ6Z28*n|C|6(J`rA1!^{7vRqvwX zeMpF?iwiGR@Bduj&KBlN#FPKMPm1XH_#ax0oOkfFiHV8zxX9N{|7*1VbJt`^s7e2O zZjEQMveTd{qBE$0FF!)wUmLuz5l!+Px=PGsh5bH zT<*WF;NJ?r{Dlnsv>?>;ZTPI|WUrIvV>tZHtIf#Bh=_lG{QIBY zZ8ef$rlIv8%=6;IYiIrS(d|xqN*5ifzRt_q)#rx~?%+vdbVf&7-7Y zbyBo+mwnemxG01!weC^g>hxW`IgclpcDAH^MvRA$F>*h{;~kd^ z^}Gve+P(RlYkNVIeu>byC6qL>)^~{FAMdy4?9m1LGuMTgJ#S$854Lvy{An@zos|v| zqA87Bn>4+i&MvStm%`YaT4L_WM5m@k#KsaMM8(BX-HtW_QP42;PIebyIe+%<(c@sF z(|C06BD11`^xeC6$W>AkU>2tsl%N0T+nZ9<<2i2;{)enpV+qj z#3fP1?h{I(iceoBE}=6i+~4L^hWAADG1ohHJM}ocJPDN@u;@_2YW!9Xj9pxd%#LC5O=Z$&&TMw=p>QU>YxcLnuQSFQ4chHtPBC@mZ;&nVwD7e+~`t|E1 zE;Hg;j{|v1eg|xIb#<>miD3MwFMA~jU zhy~CR`|Qr^Mc>xTP(h&iF^ZE;__6vgMEw10iR~vUqf1OEX3K0RNrYdIsGkXB2u2J( zK+VEdCZr9`%9(z*N}`4OiE{fw9-k?Ft*=wh!GV*Lv*g{9G@>O#%-{CVbbc%kd25di zFsZi46uywCZsr<|b}XYWRd*C=*K?TkQ6gGW`0PnP5-~=JT=6QT3(L!#OKEG*Jg9bg zCW#N%xRrZde=SVI&NV^D#YfBiRLs&G)yz)Z(yrG3r4J*MuT)HSmE%G~bFz!e9q-P8Oo_)1Yf6GgBQHZjLRuP+XTu&Fbj+Wwrgu(OTC~2Ke!vr@ z&v9of_~%NU;keaZydYcK+_sRB&HgN8t*XzW47bMM1*y)3CcTaeC(75E7bWVc^R#lRp7gxpdet~$b`2ak3EnyV0EopIR{F z+c%bx(b2&P_Pa?bdK`y$d8||DAHr0w8EVVP$stF|a})AscH%k$$U7$rtF zw$J6dDtQTw+dBkVW!RXKzO;tF%R`dh5oX4TNOjHB6MC%TqhGEYpwAs);GunfE~kek zxlb{82*KW#QYqP>m7w3L^XhKn?o0|7rTQe5B>JZfJl?Wz0{GM86c6V@Fw8p5e$>2M zy7+WpHC?0pMDg&JsngcvN=&Dwju7mar9A=u6MKSM zlc?);mx9OohrmvQ|JGEs0qmZWv(4hYHUbe^0RajO42+Tq%R@y0!7N6$?zt&${C5@P({dwZ1~n+?Rfp7Xd+d- zT6n-hd1)i~_-yVC$A;8};}6`E1II9qfBWt+cRu1+#NEoGl@r+gh-;cBe8}H}rJy-t zqJ+Tx!1}f?g|Ch#oai0dK=Xd@ikFD!0J!Xk4|c|M~VD4Aozb{%@=u zI+}KeYsz^0_NAQ^&D`o4Y-;#dv%0XXJHqe!-=yGXOcT1zsuAFM{%=s-aeep;!FJsy z+qBpDR?W%>O8CDJT)h^u3Kl& z@;n-qm6e5)tJE}Nr&gaOXp4mfpb;TZ?}fj=#yWT2)Vn@=@Vi<2MrVxL!pT3Q8k}a- zIfII2RB~3;{a?vE1h>PaNDk9B;c^XsPX8p^aG4$a=^eiKU_4#(?oFva2GwOjn||qh zvQ1NFwgBaZ$!h<^Xn0s~LuZ4YiHXOhC_m2J4vza|x!&iskPT z-#%i(jh!v2u-k*(!h3%{#a#v26u2g6#NdxQHh9|PuO>UBuFZX2C1X9JT_o_n+|>O~ zE|{z^Lx%j0NUE@fw&0~ni{kbjuVaD3?HP)hI!FI@{Y>x4g#}mYbnh!Zr=8gdG94F` z=JS~y+r=L@M#jgNw(EB=5lOwq@CVT{^7W;%re+vKeLQk5Z1$!TdgMm$7rCYsoZHA< zFy7-1&OLvxLz6hT$?l+Q(Pw|FF^FEmMk8ie^L$IPKX-j|Xr1d&npF4K$0wbeCx?Nv zI~Qip^Co5Rt?0ZzS&%rM0rnHx$QbV*E7A@_&gj@TbtIP5yVx*0(wtqf8&pOa9vP98 z(dIxmiy0j=Y~Nw0@W%>b3z#q!Q<%8nanUyAa$5f2P34Z+h4Xd!?{|NxmOrHX#PBRB z`cwZXy!?{YJ$j#Yxkg*|dMrld5S1@P=Q49(tRhF43mNokZ0V?G%$IK%8yhpE21HQs z&_8+d@^s+uY-4?Az_$mM(=|i|YQTLt|sOSngmo*449I5A5m_U_l2URyp4-oI=kqjgGZs{w6v-`7b8p2Wx;^P+Kk z3?Rf1yo*jKVce>J9bRd0{)4DGS=fA&l9wZ+om$9CzD(43d%Bj~b$;j4>URl>{c2x3 zBNsYWeLqib=o5rIL3|7DidLQ|ETft^5Zks;%z^Zwnx?BWkjgOD7r<~%ke!yJwWg&<6 zl?T6^gpLlij_1*9{<_{6ZT`f+Q9lU!9fGrauu*)zmg8pnZ@xR#4Q)x58cDzDhwYOj zbq8CI6+adykf-kHqGq-fw<_HnQ{GS=a-^Hke|NWUw(G~;lm|JJf`E>&K|vQSN$~$~jo=SG%%in|9kQba+Qbs_dYNs7EKW-WI^W z`H#QB+4P>%l$hRtdATJu6G-O z+rS{q8R`r=BdzufO9}zBbRZd#&8%Q?+?POHvc;|HIcwF^VHLybLcxdn2kxu8WA3XZ ze~whR_|UnY-jH24{(cfeRO2bh8%u&`%YDPtoOo~J-0^qW&roOQr)kdDJ$=J^c{Oj! zGAdy}7ekqg27bWyCTwqSKLODAbdM~wH<@P%rv2y<)>yG_6cUys^Vocjn?whSxFrRN z^|NAnBqUb7?*TU)IL8V#gJIJ?+SxH1{!I7y@!(GT#J|Peg|?cF{DL*pi@EE|^toBo z$xq1Bt|aRI%SRW62tn<6IOr5d;nT57oR%_bVt;XZ=z0#!_;_G{G`RrS9QU}e{&OcRAyhZHy*|^Y^{Gu??@AJ z=Xw_&*?n<(@YFsMxGAMcUy5@4d9$PN=`u;f#s1GEe#b|t=(0U?B3FA+Z))ux?C4gpU?VS{93Wubzo@}}CFO2_-s(c@@T z4M3|4yp#gFY4|s3;j&dZj$}IDbepLuJKtVkUAh4BLB>ulZtkr7d>mcx%ct5N$ph1r zRTUMljwzBpfBS~_@#9BoBjgeWMdQC-mIjWHiTzJFbyI{2*cb1mN)UaWQ^w zAlaG5ZH=y%-`Lf)mcje^jUO(B_qwn#v$NwqeF{C=9Jk=M9e6vEr(AcC{v4%#Cej=B zuW&+3*?uD7kiPm~0;?>9f~>3(!!Tl?-q|MVSyi=d=}Zk#41(VGIjQoigy6MZmudSg zNwxkDSGU(kn8 ztv^!ojvf#&UYRM|ph`6_;IpxQ-XK=r6aA3huE9fyFR!>>*^Y;~o@fT3;l98}0E&#K z%bd&F>2|YOS@bJtg|(^qcGR^jwS^@(%JhWkt|x`#3i^*Y;N|hO7#t zXZP}hr!mcc*8Tqd<~{?%BbuMAx$ei?j7&_K*`7m3R_H%(`SV6!sFLhxlPf-aFZI5keOeHMb+&$N775`Sh)e zhZCND{cgyPdCO9H-F%Q(YZtSnxLhns*7KJ4lvpl(g(Gx@zZu1&WNfzN*gu_wo$>7d zHf2_)T~&^HUHM=WNOFnermE#k-D{>cGCQi}vQKds8*_QrV?Q_LBR9HHE2lGl?sP$D z0Z6>=C3$+TAo6Z8;1AyXQfJh#Ix54xduY|uc40-tZ&a^gpeh{$_Y*Uum+l zYsbA;H)TeF~oI!YZiFePN3Yi`~68G>Bq}m!6r$GRo zbWcH<)_^qOi$&w1q;`Xa+1sXe<#yDujOL;+zqH*siyiF`>_vyxJI)X4ew`r1wV6_G zeRdx&M>+Gpdx0qG+euNMu@xG%^9VxP$D3eRYatJp0?3k`4nna>%+;Z<@D4~aS=2g zyC|`7aZlH+-v3=}v{iigroV<&j9+)qr{F`Hl%!%c4~gq3otqL`k*+)O__v%? zZ#VHiQpYUPsKkMI^~0Y)IHZ2NF0Aj5?>EF)b}r6*WQp|NsG9Bqz>gnwj+?t#1I}Im`VJE91*YAghR9<}KY%i8ilZm7pOd(;D zO)fWb-nbedGDP(e&yyszM^kieoOX2RF&}g$o_G=Mm@ZrLj;Ge=V8zcl}+*KH-Lcqt9K~ zE$*ew9r6CV+$S=(yk+XZg$Tu6`%r5+U1^cnQ7Ch~J(JMQW#!A{e0EPJlJOmc?K@A5 z@sPL~1Vvq@FSS&}Mnl$u6WT$ueT5&Nn3(ru&wPdSPcJM?4Rk|CL{7Cx>uY>DWEvzu z0WCIkv-8If$rZHT^!J&Q?btbiFJ-L_kb?>9&Mh?@z@x&!V@5@!fEJyUl=s6u8PO9b z?06Rl!Rw6-W1w_$X`;f>4O@P|S=s{#OcLT;#ubptJvY zb+HgIjhHJQsblk2`wp25@@1N8UnE5Jzuma2m^**gx?uZTdo7VVye~C81doTd>sO|I z4$7tb$G6Tkwp+JaPtGM$38y~#57QxXR!rPKJTocEKcC$gEm*fiu2P_z34$aHFLo{T z|5{mgRRpp`8-3JL_}t@}q&0qngyDomLf*a0Pjq<=C^na!gcF~XZuz|)RG|?XQ_X7Y z+_)*yGrW1P%QKW%eO`8Ug3-~~6*-?ZCSUfD{c8WN8?u)wjiwqZDp~c|zo(PNvTL1J z4%dehu9|?6!DtQ{ymJBY-PO~xU;A@*DoGvK4^W8DBduz8IXC#a0&b9S82`E>e;Q3% z;pS4W>-|TO6Vwv&kFf~}fw0-!v|h6I|LIE&YY!u{7;2;wdEzD^?cw23K$du@WW%xV zyik|BmWqP+48{KJaQ*gAF`);$fht$xPAFT#+Z0)%wEW4mycpPHav^;TZ@hnpZd6|f z)kRUu^a^-O40q2Ewn~(|mT;&Qm2AD#>~?g}Ecd?l$}L1&m~ZvJ^H?99YKzCFVJ~Pg z_5`%vP9WYwhT|bb_u>Tsfbj?6Q*Fe^5KM5YZxv}2>TOR|v#Y46aE;UOJLCoHs}?N* z&C@HN;IJ5DX-}w{)NorH$dprmp2*e?f?NWZ`d3-q=S@+pnpN|F-BgE$hlWUbhBd1! zThER*pIRZF@g0Hy#(YeeXScao+$=387rLFYR2`Z|d?NnH8^tG1)%=k+cAzg>3rWtb zCw>PZO4hs%ZS44aY?SYHe1x8kLcd}PMY5hpG>Dn~{ayO$^c3!=1cV^tX6B`(rI_^e z;`hv~tVb4cd%3?Lm_3Gh0EGjkw6yehl@$dN=F)hbh`G+4pY`n~UR-!Y?NmYGCW_m} z!niMG{XjEJS~bYs-e88({?D)0#rCj-S_;Ip-A`7R{qBd4-40C+O-wBIhXVow*EJ9n z5z_Knv|4|khNh%Y_MUyD#m*}#l1^mPM%0Wm8ZBSLe#=k1uEDi#pps5V?h9 z<+&0Jiham+XrSEK+?NLzE$HdGm0R$SE$Djby8%(;@ml)*K zC|OVDTY=5|1T-uH=SP5Kg&*P}ka*Py^@;7gC;+Z1^W&g1iDx?D37Z2cj+9oF4A+rW zDtk_fWt-%V0)y6Ch9hCs74+Bobj&jc2M3R3JH?6PD~AF0HYfcugL zV~5awx3+&fsr`;OZ6>5y&=KcprGhQ(?^E@gPM*sCmme#C@2Ru$A}TA{Sl;Lay)>b! zv46ox>4ZXfBjh*dc#)f@q79j)zJ68*M&I{9T;&|Qk4rag3?x3Y8lt3{0N>*EI4NOJ zq^$^M*;R||S<;>vLu;(j+6*ZZjRJP~h=g^r@peRYRjzXtrd+zPXLL$RxI!xb;4`mm zRaADJh7&(V??JKU0G;L>ZT)U8p3g_7+uF636P&#%`k?DjucDu2|F-=3I6KY1OQ2&k zjG)PB!TmomDf$mG7>-sv&2e(OzC0FMH1w!-uK(SogIjj-rbgk#ixDeLZ&IfwSp@}Y z5KM$_kD!Vbq65p_!+3dxYCYatMtrB?hKD5TNy#1C4@L8=G4sD-=Ck}}_K3uMm{2`z zNqOzjYf4;ND7T#`SX1eyRSbW==F4M!gZBCtvN8q&(~&JM750WygGEs-CKD4ABO~L$ zvT}V=8UQZo@H@WMb6%QpGEwpIq!E5jpx5!b?9$S*iu%}@dG z@9TooDT*@v+Xy7K5FOpQzB+DRf&iyBR9yRqyw?-*x3Yn!XTQ+#JirN`oV91qpT8Vp zP)PZ0p1Z{}=i&eL<(H}+p{?RumBc5J0^2niJ-T<5(JfbB%p;PrQ`e^Z3tJXlw(8J2 zpXs1z#af!7_2fkK?=Lpbx?7LtzfR(_|Ge#-+fb^sRV#rH;*Gem@#lSK_l6yhS|93V zsn%gtkoc4*e&=3&=!=b4+;ZK*4ZN5co^G%PZS2nd+FjN9??+^{G`%T&FV!Z7o4vg~ z&ep%U05W=P)I-|KFjQB^-~L=(LIMo}M5*Vw)8CnTvdYRzz#?7!{W4-=DC86rPgl-< zwrgeQefu`@D^OBd5(>BU_wGGC9SH~u`fglq7T=~_?ri=sw?R-YIQ; zz4a_)HUx=jTBpR*PW(FZ4IZ3Wd+Z zc^*A_q@<%$R62=IKoH!jH?WKw5XN-x@MNQ)n8Tn0&xqt6)$$GszYhMy#6*&acT;B& zIi`PR6f#9Hd$*Fd?B8vnciGJ|&kKm*X|=3qX}L>ei6iy)H8sm0CDK=EtyXF;T8FDI z$w;tzB{g2?YNZR~m_0_*bLJNfssHvtT=P|z0JqVDpl=)r&ZgaAnIadv{$=IQB587# zA_K1Gnc`S%AsjCrpoOGm42QX1u@DXls3hAt;aYo61Si85kM~zF<)RQjY%mxW% zyY!`cRXA0SL3hFDygY0*9oGj`h4nt)tm`4MG&2aWN)=X6<=9EBM_5f&A;mV>bVsIh zfXkUkY5=*pRgAVvrU`-qhOg^&`T!&d4>1OLDD~dAr>ag!pOPC zUwxEUXwU2(LMzvNZ~p$KD1BXm0IOK>&N{2tX2i3~vOZ1SJ#KEpN%7kQu8T`co{?c; zbhsYf%1<9Wco6#cb@r-V;k}=JA2^Xx>_Z&cer7tl);8^xc3NO^W@cu;OAWA~$}+s& zqw7G(w@|1%WPsKiZZ>IDdO_ze{tyjW)qb(%v%#`9&C}WK z@$^%YSE?6>LO+wwNAfoBuZ~X{4&HWgZ?fu5P}BM9J~jtCI_zy*(BL3h3MhGcu=J4^ z92y#$ETl4>Ho4j-q{MfiKIi$-HyIu>CxSjWi#@1{HE0&BWD#7@gd?7cmNkr-S&B+; zBR=3$KQDMbdTJk_nThzos|3yYjG74oROk+X@^t&sJNB8V~a0&OWArTd8(qX-TbU^Fz8q_kkT}J}#c- z*WUeZxQ7f?RfZssckM40O(qJg;)>bNsrk~{aQ%Bq7MozM9;^0AwD{q1_8;zCNCJ0~ zxvhpQ=_5iyc6U{{o&LVTqYoTHl`H*sRrlj9=jG zGjV$!%@c;Fk~%swBu`bKS|}b<;W|U}Aa^=_^zy~O$PmPslBv{}S!qWNg|E%28fQ0~ zKyPX<6M{tyif1eBhNkp~hrl)hhhZF&w6>g!j5h-yA>`{uaJsnDyc?1at3iTb9q zpla@eFY*m=OTI_|oY2e(B3>)x!%{#o4ZGiQe^;21(5Bv+27?a2d%?Oa=VB0r^*{se zdWqAPMoTcp?rSyez~fnW0y;W6hrw`eJ*e=VK-J(~CzZ2lM{se=+DVt39u(E#d@Sl^ z=+fDHeoV+{VVzsZ7&^~)?-6+qks)5t1YrP!8VT>6UDZGQET?PiZ?3vYx=v0Wd$_oe zxOLu?)Ns&s*c>6bcQ)(GU_$akmCyA*8Gc zCJI6_vS3hMt0xx+XhPOhN0K613T#NT6pIPJy_v*~c`Jx67SPKkYI}p$&*w7(QI;qn z5hjZ+VN}JovE^9_Im10)#+qB=WN5WJE}P7=9YO3~5oHMB<+Z>+;yr$%AB8>nk+jj( z1j-Rq<;J~3%LkaAn7gh1STR6dNFFK-sB8WJBp(wOm(A$A{=|36U)Mh+y0gM9lkRzC z-c+pfgT}pVA*J!BKYxnbJ>PX~X8kBqi8UMF4$())sG@pxY79UrG1M{0Px)o|B{=!{ zHR99=8lU(OQ1J(VrqpKbobEkAj!(&(!RT#oXD8T)Zp}U&s_D~$kT9go7j{Ki*%3q$ zrYGu1(&2D!CeIvK@LLIeR-$E3@nSEr?anY3hg8N{#9oQl5e*@mEI(EfTjNn)LVhou z&52pzzM8Os+SVEGg9m|qpTk%T46A?H)eM;2!4g+ci2Ph+j&T8mare0STKm14CW(Z( z#e`KwyZ&I#;E8#h>%kwU@wYv?JIgC8Zz0J+u%Ou3*!WcGWNG0-T_Pz!hiV(2tdzW^ zW1Gw4O^8bBc{?ygzBEr{Q<(ikC8!D~N5Z|=<|u>pJ(}a&=~;X9#+$`WT9(yE$D?IN zKTGUZiNX{?@( z2#SPW2lZacutoO$4yK7GftEM;O{33~vS5!rqPPJ%{%U5|bje%);N(@&y-KlH5rX4m z=a|PPkxg*92tW7v7GI=ztyWBlOUCvinoa^KC?nNjDJd!PySe|0lvGte3#=ZmIydby zXo?o znVRf)0Gk#qe}fstHl#$db;S;4zNOWte1#92JBYT+wADARzLf8vxr@&kmB9M!-t5_* zTS<7vHRve%xXwdHP*>8iJw(5PT8JprTO%p?vi|DSL-oRTxr+#PmRm~kBgG985|T@m zMN!8qhQ|6xuTvAbRS%twu2t+I8fK_PwE-E3{`m3h`Px)(OUb8_5K2;B6yb;IGK#%3BMGPUWvsZcRBUYevMQIV zQ;~2U$rDHyQC+&H8Hdr^J$Q2B(z~ttu`QUOdLm#&ybD#`H5dP|d<==r1f2dV#V`Bk zln-8(ZcuQU5+X}xd}v6+Nhip>178$r_}yFb`Y$|JQ=R{_t@!;?1~wDz(layD?P(1r zr|M&M=1qU@**@NLYTkY9?PpFDV7&=+Ia7X0s-IruB|msGqR9eATBkZ5e*!SG0OFvU zS7K69Nb}WEu>&^&;El)je_ljA@hNUPGe6uMCunUgd};fCuBkX}ax8bdfsIVkgaq5f zZ|fC9==D>aR;cCwt@{{q=kz|kv@nJ+%k7nGY8!cqVlMw5Q$+`ndKW*+?d@?pgDDH`vK!M2w{%^twq z$T3(hSqF%hD{+O`Q9%}KnXa|Jq~^K$mbvD7z|6$7msBu(;OgC!I%ywSRIO}0QD%g+ z5tVsZhTL3sK0J8kJ+<$}}uy((^JjNM9 zYHEDhoj2tZ-%hnb=7>&9i)`{drxy~MF))apwJ}^=TomMXp}@mL$G~Vce9*RSVE3HQ@F zGCfIU`$*}GuDIy3GEQwNNze^uy{|o`CfwU^sWGm0cC(KF32}QN=OHf(=7fzsF)2m6 zkyV2(x#+6dcLmiJm5mu9FP6`9mq5iwj}4rH@cDFWjCxC)oq-(?1?Zro%Vsw!D#wr_ zc{29eA!yDZF{48{wU*&ZKO>E6#$_pj+Qh74b@_b=JuNYBD(cxWE{2R`3je52nvmb_ z_W1)|rv_>s9g6qK#bGU9wV11{3q z$>+CQf-RcRDt_Mvnn#gk8;eZ5z*`h`pz}lzwoiL19u(_bVO~ozQ54SP`&Euf8)tu>(1;eMMUeTNrY!hn?gjt;G2QXm5?gkJ=x8Byy3~H z`Gjcois!~Hn`vCNHa;KR*e1T|(9C~jh^9ZEEJ_^KRRC3wNZb&F5;;_zGJ#aVjvlOu zux2&SU2SkZ;4J6;1rUjBs4+3)>gZy_N6tsBT38O?h78bl`&z^lc0UL3K zZnGDXbYzvl?TN!)!Nj}c1C>?q29ZFRdNpkWD^;UhOg_!K+xqiM6%`H$8nBTpxJ^1c zI$+@q^I-lp$@u@vDw&19U$+J0%Fwr@gN)Yt}y}bAa** zNly7n!pgZ9MT&OyTtf(-tWyDM+21dOP%kgM%UA;XewBn?i$vFa>v8 z&}v{-cYBzN5wVtv3JU*RIzY-412Zhj`YD74wd3? z*$z)I0gd#lSEPVfgGDYD2$0STs6Tx>T!mP+D;NdUDqN&W^mJ<%s`+M3jYyP`roV%eC@af;ggVgtbe@0xu!O>6^ zzq&j(Xz@W=n`;&UF5FPZx9Um_WmVi+&tvVCD6GaxXB{qcGvAKGr}I4^#`wq^?D5t-T@WHMl4dgi**z4MSy+p7<9ZcmN;vuA@= z?7Ezz6d-X(&oy}t!rk@m)H&}IX{9S{c1cP~((?0@BiBu0WKY~Rh?Y-MsiMbtA)C-* zqXH1d5+fv}p^4IIbYlwDP>(5)k(5OL{{8!!>COLcB4MU()M6w1Wo#dIWaiuV4nEZ5 z{3wb&*l++v0p#_dFMv#0S^3l4iG=-;tfFEkSVai1{d}4)w`^R%>N!wrZ!$7A_WkpI z&gi7u$s#fXy`RG1!p2IT33YR)stfAOD%qgSr^r{DQ3~t{!g4YO6n5=OK96uf=jXuHJBF%=9gS4gId~U1z7( zoKoc)drML+wuOt+G*&&}3va+b+OZhxl#MouugXX8>av>*c;v6ZXpDW-4q6dyrD{yw zlTJlw} z!3Ci|uc2T~{<&2|@wt`t)%|<*=5Yu3vENo2yAwVjJ*(~VN3>=-LqxMPR7656#lHeo zP)WYm`mYHGE1G`uFX+QJvATsGOjQ*(*Eagwr=;Magz2}yazO$uC3HzKTg{6bWfbdU zsVEJgD)gR~m^*(5hnNhIzfSeanR;g#(CO{cSTEhf(oKekx>P}~d;*X6%hS~64>fSYPT2f0A3l86QtXAp zBSBgIu3w6D5>T^cj5a5OMIx&Ond_osV^PD}hyLD8c3UOHvLk4AI*f1TB-6O@0-JEU z{r#1FC`y_SVTOx|3FV2sjYoCHL%HTqgbn@Lem&+cJyr-MHo+Y~jjHI+9f?N;)wIo1 z8V6HjwxvazVP|J<9?-MF>-0B?*z0tKjEjp4fk;t!2*!ZyA8Kl9_vq9JOG+rS{7e55vc94^!p!0;u!VEq++{k^ggE!BnU5CD`eIJg71}tPq2NxK! zg!byyD_Y2({+Ksa#*ibgq^z7Ncs~3^v2DSYv1e(_cE)i$6ObDA&71Aur7UqfGM|Rf zxi*v=w*O1tz~CKH|M$K=rvdY^FzkPr9_lE;eQc!N2Ie2x@uL*^373GN(*YAbtc;A70#sTC227+S=g+iK_FxDk!lfDKxz~S6V8C3UPbQ)L@F!dSi_$m9 zGsGzhzegrlO}2wPKx6P8)Ed z^-x}xc2c*Y5eWLg=rY@3aBz4IOu6N(6Jb?i=RhXMeHqE7^q_omDq&NeQ8|RdqEA|vY%l*<2=4-CJ(vbiKY$>t)TQeH$HT3MOpwKP+o|Y~mp7VfsKI9x_ zk20-x;pQ1};(ahjw*zeORA9RkF51=CC#|9JX^vg_DcFGpub_OVn0@j3rIr>FpOORM zQ4yuF-hHWXaoTT$?B3z^B}=QPtez$gKB73--Jl4xz2P%xiQuJ9@x`*?5T&Jj!GN}1 zFL3+i!w$W+&)XLg2##EXT(&u8F0Ol4Gj%x!7qapdtiNX(P&?(ynY?n zN$vhkDwOog@Qp9SU)ArMM#6{_CL|eByt`}L+~0o+4v7-i17m`f z;!j|U%mx!h&E>zT^&I1v{vSu}@7IM|4iM-RZh~i+pX3x*~3Tqv!?hR2fgQH@~vylHf++?GZ< zA4f(;=4q}^uz-}xJv3+!y@kw|p#O2&+5D-B7_%RW<*&+TwKE88xu_|H!uP%bXSC}b7^pbR~$&_zKB^uvG9RMN=k!6VR%DlOC;)`u{-lW#)FWiLNv zZR9Hnzw>rDWF3eH_a8h!5>lXlU=fpj@gksAPgGl*Dl{w%(v2?+D@+JXqtB`<;PjRi zJ7k;d&6_vn?y@D~LcGr_E><4jYIcn|+ckeUudTbeTxDr#c{o)b z94;u0$f&C$hblnG`}fM+Rs;Q`^j6zXl6&(C3#Fbty8#W(Z#h3Iy?%|6$DQ^Ry4`AO z?)cG~p1s!APF3-;AIAfr0wDS=#~mdI2^$;cx%h(p?iIPzzK0KLEl=Ixke*A3rYZc6 zI8bCl{*a$5;?TJPIqHwwEHV(65uwN0ZNlaSKZEMoPhfr`=vY_=;K2BFH3WkMo}Nqy zufXy4Ya^MCu_Bj9F;W>re>Z!JAZ1$wt6*@K zl}sY8+146ZAwt5!Bw&w2#Ud0(UIU1xp^*_C4-Xk^)K8rA2G$E(sgQsIAfvWg zSKosVvKSwEN(+5Ji^14cj!H_p1DanZ7|ij5B|bLiZ9aC~cm)9E;(YE}bymjot&qpy z1}iq`9>@mqb<<`(yXBBY;{|=%Q1mR>d1CZ8zuum#ojdRK%#sa0T(Apox`?V-+HmLi z*CX)GYO+^0YBMbV3`g*?RnWsr{~=3<5-$ddpX{{2iKZ#aFTIP~Yk=Ou;+qk>uqRz# zUx`n;Rzq84aop!I@%v;ulBBjLvNt)Kze>*i{63JaN%)sLQDEkQsO@{`DRN526^i|} zmP#JJ6FIW9)*oSgTq221bSU!TPI%-Gs8QaMQh;0;7VicG);b1UpD!3*iuULtkkQ)n zkvAPvm1fq(5f=1PG(Sa3YH!GkH7fI^;2SQ0c{Oq_0xLo`is3i_F*`3$al46Y9`xvX zzpJ-#N=MW3wiFQ`DiT}Oq?TNcIHq6hI45)+PA76YlH@Y<#BS9f5O-Pmrsy1frHJ_6 zB!qmR!u|W`0?ylq`4@qPH>OoqY%*+9G;d7Xdtel)fAp`>%zwM_H-M0Zo^u9gR#p#( zBwDxd`%U7inW|{^$d{?zZv{H06LJ7NgPq z_@CR=BRXpdv`QoDoL()=ve!H;ui0JKLGb9)CDmjmj(s~5Xz)P zl$6u@&pB(U%bx2AS=?`Q6D?CRFL0~Cobby7HcM?m3NZ!@-+qjtp+-jT>R#`&LI9BJ zLodMZ2G=J*Pw+6&kWCT|heOXHO#%1~Vhn|BkBrZR5RQaB&p>4&hO7bomr8$BkPPPL zO?W(kL0G@o(dU3$Qbf@7!t4Hz1<)zF7$OFrDe?M9%FysWgiK3r3c2Uc7aaJN!Ls7# zhuZrGTL{8vOmcGAo|S7;QPT3W)zdaAvW zmSaba%TIIfsA(`wr2@NeQ90$q`Z3vLzm*WoU&*x9ejPi!p zbK)j%PWTB#n-oJxq77hlTy@o%zIYhu>ZM2bZmFKW(gmZ&+qFFj{sxAz=IWn>wpsYI=S~B-sm&h`z!euY}f<@YG=8B zWBKXn{myc|2acknc;yrn0GQ-$?txSbO=|Q40`Z!qoU7}d0#9I6Th1>i2eedO?3^M043 z@b!nceq7ydnOIqhxxS!@xh@unuJ*Y9sOp*oz2ji@lDK+NEuOSBYt88aJS)WOvP*8B zEsRbW;y zm*WSL$r42}&`p8t#fL(-YrNDr+7PO}l9E#LX!g^tu%E2TcfdpT=tInv8_I6bH-{u4 zcWz7q>hQ%yeLxY&+73w8UldaPey*V256b~>xE}a(L3UeM7M6_Y$jB>5L_mz-kpO1<00#lrAcX|V&P-@) z0zm-&^7ZSp?uVgBRF>?RiJL%Q38#aOZv>rWc0Aqwpbv2weP;%zUdAwn7^3qXWKp?> zaK=zmb8{7LCM1%vu;5<)m!#+i$KE9%7ZbnN;73@cD_qVYtP1W24 z0RaDyqK?9sC$u(LVBy6^;+L;bZ@0DOK<^fEh5oQx7W2688{P#aYT=$E8^nMXLzxi? zIaq=>H#gtfbYN68@P#EdJUF3;9Mj$1jnp(sZRUiv97kV+INiKhh4lW^JMTzC#yI=8 zRY2)DOnLR|9X&n0UToiW!Z|D$LUD0%(Hwa;r+O;N&Zkp4vl*MM2ZBf&VvlYebgCg6 z>qViwn&7Hyv6(5OS1wHj)@J`}fW^oa32l{_H^~FQ?i)1|;f8!Pkj21HeT<3KvWJQBa~4+nC(>&Mnc|BtM%fU2t9 zx&{S7K|(3%v}mLoq+5`ZRs@mm?i3KDM3j=05|Qo_DQN_0q(i#{wtX893&bQ)@g(uYeA-0~IWFI(L&dm6TfuxD zYcC+#?iLxscI)a7sfMOZ$TdlQ~QVHMAV1Kv1{%Ed8XNS}eB^~{n zA!>M|4-E;MR>LhO6e?_S-erN7f=!{q)4&_vIbWbLPE_d~LoAvH#C}K%M#QwL4ag!JO3Uqj$)6{{$mQ`!We=c;hEOd3s&Uz6PU9vNX6O!SBpZ?0m}0dkD2D?1%U25oKK9KLyFo zix)3Mjg2#U9z4&>%_S%wfY0~(_3O6I&WB!J!T{yO?zov5ADNUsfdUgizxh3WXof)j zD+bO_kjOwKiZr^+b^`$RYyuf>Tzv{K_^U|tPLp(?JcHDw?Wy*yRR{jQ-d-Qb`5{p& z(yEyZW?gcFs2kLsrW4uLCbRoz3y@*ael=azeN)d* z#{|E39)N2^F)s95Q42AjQ=n`Vx zjOc0VXg6=)CkdY-_*&PqhTm{j7;Qown#qP7KLHDx}%nEGg<1}fZ00QjK|L4m*118WA8|0gdpnqruD5 zHF>D!0hxdk5=khaXtuO0c$#U-Noo|ME6F3RrS*>18eodvLIaVOrvi8HVnX-!(P+D- z_dO;i2?!scwYE|C`kfFBRVuwN4@-|$`(ECL+Ipui+`hE*bg1fkfBpL8o>g$Ha9k#_ zu6b@T`f(}=Ib+AY^31IMtkURwCj~z#diuK>{jh(baW(x+E-x?77HmT178a_8-7p_@ zvk)skC$hupP200hwkdp7yBCTG~6GK%H zx!T`TgR}yo4R9-&07?dV6N48NA}*Va7-E=P$2#x9N~lGy3HSyx6*TzrAa@`jCPq>k1eSw0fMO7^Dfk8G^gnMk<3uG**Tf{$q{shDZEkl@o@g56{6d*}ZtA@kZ1Kz@?^&c_N z!JgMC{SQDj9?|(s?)E=K4YmY@PdPba(5k)d4NeJ=$awDOLB-hezCXoW+$|Y^2hHy# zJhyV7Rzf{saMcyJyP6aq9}GMTEqbg)c!-hqGJ7iJ@sv;;!XKb&2%m((*$WIRdDwf%+w2geO4hDos&0LwwDK6pHzG?HlYZbOIOx!6Ym zR3QDy+Yfk1Usri*2Q9jS>jxbtCxW#?>5bIa+ycNnh1T=Y^X19++zYOh(BwjzI}q)@ zeq@3NgFJR#9JolwQT6Ug%dh|_@2&$b2)&D+ZF3;5h3JeLtz$oOqY6+%_-!}{Rp!Xv zC!D~wn&<8Atxb`icQgC>`Sk+r8xD5K$)Mn1#vTpa4_ym86KPrLgU!Up50KsVA1g&j z!fhMb6BIhq3M>?F;^Tk3TR6D*@mSu|vvwv~<+WrhgAr_Qm*n6s6QnakD9_~jsFv&V zRRKAnCw^Tf520QXfB3Kuwv6N}qF>>bdQ08KwLoq8~J!} zKM?vP};)z)Ntz^v0@{qIOF<4)+qx{fyMV}w{*YJbK z1CVe4%q{t>k5%VPfE?#vO|q9|^$6q)r~vF;;Q9H?gig%cxz=LHoVA-2`{MbHkL%*D zzVt>4wmV6Z2eoL^5?VUtRpJHz_| zcoG`EA7ml)83$)scNI3!QGv%}y3Pc6jInRure$Safj|OpE{dF9@}p#r2*6bce#;jk zVy4jQ%E}u6eW1cfv78M9>87NubzB4yB0j6R1Lp+tkBBn#pjrf|-ld<;p4W6SLs5g^ zIJvr8os^h~O4&2`4~4P--0`p?*p!sc2_|iZQ|3ZU`uquk@w@H+$-&ftb(?C0xKbWo zjv)k>NLOZ>Dl2HUc1(n1m&J>jo+5wc-(MXd%Nf2XTNFGGBo4VVfgeedxmwcFOEE zarNu~(4lqDT+|BH^>ha!=|SWNQHw2PqHuDFYn_= zG41I%<|*U6T+#KMqM}E(l8ibU*Zih`hL%I&U6d7fk^)-^(lDqxg8_}NCsfeLBZR$U zQamy{3er{puXbgKCGkO^27QYyE&5?-(5L3+$`!qdU0srYJG$od9Cd=aviNpD12io% zGSDEKhhGX9u?T86zI3Nj(218EX(_;Vg(FGg(O@jiaP6m0ZRzWfBHd+W4W6)qKYu$% zjErzBf%wf9Qou|Rq~`?u*Y{op-EYozDFy+u@){N7PnddwW^zmO_qNE0M_^d$H40Pt#B;GHxcqp zVU27N^l8cH~X)q*k4oL7k^VT z7v%JUulM&yF4GSDjs*`$!o$Sg%~cUcJ0|di)$T8d52cq9X%Ju9pMVp^!y3+{k*Cfl{rW$r*eF(cv&VlOYb7CY zxcoKZbuik7fbp;Q(Z&2hw6g~&= z6!E|Z7_natG9Y;^1@uG6T>X^5ne<RNNpg}(t4pd0L0qz40FSHB-zOc0a@0-Ej;%|_H*|95l zL%}_UekHQViNXTA!FQM>+$ji5orz-s6#=C5BXXwvO)ru74*>u=4lZDwY`fd@?!#19}G~03v;WLk%H^hK8nrb2zNs*Kqr#s#T$j11Aso7(mGw^xseZUl01b zbqHhzNWU6!0f!nb3E7|F+&*y6)}){uhe`x#l0wGz-)7+d{v7pUAb|il(+A2NXp;A} zBUh#l@R{Z9no6T?V8BE{NpD2C?D+W38ClRph4Je=;;y_KikPA($(ON%_RY+ZZ;G_Y z;rSv8dib(`KfwQf&G0EU_C=`mO-2@Hc+}Y4`g%W;gr1*~7`CkXv|5=lN4AmXFUSpiQa{g@!ud@^r*yj6sULfZA^nCF_k9vkP}OJ;ux< z6E3~$%YtJVVQv7-Xl#}8U%U8UAMSSy;8cmio}|#iL!NBR7-jo*QOkl`!I_YMUqsvb z2g@PAD2Dt)XyIfB#$kgkIVKG$anJe%IENoxC`!?ZH;bcgVq!%~d}(RY6+aQxIDaeP zbH|H&MmiY3M)t-{v^TqdsM7>&Oj7srt~_4*fq{l^Lf5EA=eIdNZpC(Mtn4-NK>@q+ zL2eIJV1FAW$SVE!68P7nqC^(q{QNxJV$+kV6!jxB!X(A%km}gx52}5UUK?MDfsVrU4B>6H_7hwq66l6Yqz~199@5p~eH|^itcyKP%_GXz)!hxLb6FiG&pics8XetD9Qb^(_Y!14f zUR?SfO!;Yqgpwl8yLN!$?ziZQd=-a&^oJU~LqC6}7S-WENQG9-vS3fMAsfOr$z;fc zQWnMMO)nnE84zH=kNR$XR9r0-CiqcFaQi>Tw%E|!@LBZnrgEG)GVn7j85XDZp}ryO zP@yNhQGbYT7nCjHa7KJo6{|~2X7~DPGp_PjVhw*f^99VjC8nQ zwbNQ!i~u&UJ6eFm7z~IxB6j_k+ySW$0ir-UOkk=l4FQSLWf~QP!$jcwiV!mq?PXO3 zRyT+ukoKn$SPrB30Lz;San}Kk_;UW59Q5lDcn0Yr)6&|A0kA`52y`ESw=N-8x`+S* zvC~`5|Noy%MF^m2GoZsqMM3ze(0j`)MpFQ;4?NK@;HEWMyv?^5yC$1Algk`v+o_8- zJl9|)Vtv-xSpGdwhK~=WvGK~U^nPju-K!6c$0f_rh|o|$2Q7t2*?{cf0R}mUlU)&f zd+zcqlWT^`U%!4u3>{D!K!JgHobq>~H(M2d%-tp@kGLI@hVqG^nYsaL^eE?jro`yd z!bB_RTtE`NyF83Rz35GsozP|CuuSToYKY}1DJ7d8(l@s9=qZmMF*)8VdRB=`5zabl z_R*)*)Ohtw(l)L)necDFW0rbjNT>T2&mj`si8%zLr!NTt(}hf{35_CO!@ zCU|iaJxoTI$3y_#%|h=pEX1cDI1mv~dOw4v5oiRY%dIAmHFyddkyhXhfxCJjn7!St zX9Xb%n09`?wRJA_mvel3D^sb`-(JedX z{XCd3xxij!H|wWIxVO;O_5qLwi2X?UfaG20vW$l~x0*Lv8h3LlK9VJUuNeGw;bI*= zZqK(6u_ShfouAZ|jBVj!{o8LZdv=aMC1aQs;8E_uyMDI9p-?Lv1t}OmWs45mY~+Rb zz~)#lYa+Y^s4M{|?pDt>nJWqmT6Ij9RE$jw4?W3@%%n%oC$@iA98eX`?hS|8j0}=B zmWOjNTG_B zn<*MMC zITkpY*n;K=aWny=GlUBQ1@tQr_}~=QYy;AN4Y7C|H7D!U$Rq`*MwXebK|}{@6yZsi+3SeC6$F&*VqFzX8pJ&u@sH03&o^*OD2xV~ z5GV2%gjK7NuZ5a+Sop#KT7HO(lz)`9?rdKN5i-34(Au9OiBxR$uY_r;?m+{$&Qi1^+7V3Q&#d%|dgL&_Y}_{ZC)oj-Os(sw6rRh_L@ z&#!Eci?L3%WO&X+RC_MDA53J0`rgUj<3Oi!muQc@PYz-y5_v_td5ho zJ#U1qaR>bOVfB&l+0jeACJh8WP@w5}5GAD_ccROf_(zFxGD&iN+G@`)f^;X{;Q9Ev80=m^Cd z=_UbciiQID^*HE50cKL!23J_(jhY=CJ>6iao30@L3Emm6z$y4C^cRrk6G9B;UzNNA ztcp8Ii46~Ng#rMGm;vR9g>ARX&!g5HB#MCh#Xi^V8j%b^{ z7J#l!{X;k6OX@X=pu~qNir0DB(Z0XATOlsccnjbE_zULaAks%SOd4l{(FjIS{PCw< zoPBo5pNN0B@1vY7_zF?fLB{tDj0p&R2l@^nuh>FdA3>lkDHnQ?^#ZYf{{p-`fam*U zi2=LXJe-Z3g$WnU=7qIEAFQfgb^F2pUoEWNC!KWP5E48;oW(;c&+&FQDjtE7Ugxx? zv!ladLJFE627_fRp3Xt*exuHvtV69M&cDhrNVq*|1o=axN5LB8v*ubxC(87?E(Jp~!8`CktjcszvG^q@B_-sdbFOoRxhRvy+|TQA+0tAwuHw-x}iz zjotVkN)A{`&6F@w!t_?qCJ%nfbY!$NaIB21d3th3+iyS7Vo7Is5tr^>WJcuCmVp&4 zvUj}hQ-*8#J}%rd%&c-I`G7vMLhQlDJx}K=S^4ND^(>uTocRfI7emUS<%ZukCEF4* z-%78tv-@`cayzXyA>0KD37>Tk44j;M9Bh@3&eGLn!|>x7R?D^BtTe zxm^EF9YKr_X>gK%UPthrtk-N+YmUCxY0hBY7sAmH|3zT6Co8W~e_ zXDC;nJrqLRu(tjZg{~gC9w7uE^6MDoVK0(rqrADP{HR^Djsb+^g~cenyi+SE%Xp3ygXAWjex8 zkZaOMQgiDtuO*;0#D`42>(|y>ta^|8sfH;b_ER@2ERK7AP>m{}dVuW&qHC!D-{!w3 z6=H7w7RMI`?Eph`vyCn?6|i1#0svV*JFr9x13ev z1+rfy(?=D6wQs>Kn}N*GW!e`5IDpGcmQvvO1!ook>I^Oh4tWDeH^U#LOZ^7YfC~tM zg`E29VBQ2mm_vddh_FcDRjFY|mNfTVC&J>M)CqjSC1F=MXpZUgU9Lnq5l)VvKiZgE z);iI;zuCvlM#$#>o7HOmdM(PxlOX1iu)zDS0xpdl*bgb4D0jayEk2ZT_LyO__0_Ny zI!qpsk;2(#SrXqfWE!s~UiB{ckU+8~C;F_67nkpznGF?3bY$X#b{To$6y4)>(m%~? zOgf@n`9Vy7Y|iXA{UDlue$Ab1Y;rf0toDSwMs)0ZxJEP^{^~)Q`Uf~U6tojE(!=H6 zh3r}WR3_CTus9~TuH5s~Nse-;#ulGv`cS*D5v#_tFN!d-5V9Nu9qXL zj`<-cW~dKu{*8i<&dE2bJnWDonz10Dsvr7h^NNJ_eOURT??%q7B~%!i6y`B;b44Xo z&}qf*kF7So}pc<7xtpR6J@Bq79KH)@`?7m(ZmPWo84=ih-NIdP&kadV=8P>JG zj!a*OM8x}j+GBBm8;pbA8+ujE$XJ~WddcT=aiDFg+36NQeh6N|!z`?dGOS6W-NwMN zX^v))?}cOsDFPrn3hY7Nhz4pwaIk`&0IJ@&b%3hH$QRu9;`JTf-YAi|jV&1?2b*ZC zy5*W}&4|?zjE1XoZU(II_aw7h>{xrS=QcEz2k%~|@%wKvYUQH7O3f?zT!`pfS7dYl`i%!Qid(F04o6!0dORVWF4*6-y~aG%@t3F$76 z+uKswrB1MANSle_yqPKcI>{+7QoQbdo95Oo1Ds^DPoI^K*`6NSBDes;!UR^WziEmm z(FG9lZD6_st>Eb?%?{xGf0GTEuY~v-BU&%e>V(4hl}o_TfWc3_u@mI5p4XoCN}z=J zjUC5hOw(S$WNVcCVPh+1V`oxX2TMmHfaI zCrcqAjh!<*EUfu(YZh@BR`|f(MOP9}TV3>#Qm}_HR8QNr)7C2Ui$!C%ZDQ~Zt%w+A zFLW`{nBuD{l|FBG5)^L#%Ga2$s#nJ*$GGIDR%(ie|2V>?n80tGsA1ik5#Q>wsId)U zlel?rec1JK147&=JYGFoH2g!?hd89&oN1@Jg!k{Ss5}Aear?<*qPVo&67smr`4>O9 zX%7a7$|}1|=nAfG)E-d6$c;Nt#P7?jhWz%$pri(p#(v1g(r+jXX}pgIQlQp;E&as) zV^&rW_!&eo=~WHV6)-owx_PG!lDZITOs_!jWeo`@4+>U~wQSKS& zL>%q?A0M{&`(L`}W=?twoOlVcqRO!{1ktTy%;akBpEYMb9#`RTSW=D7IsL9DwZLJS zoQaXcPoB{k)qxkxdI&e0&f(wlo_rsb%P~IhHh1tT#z%C?#k6JmJ)_q|6Jv0*&Y1 z3tFBJthUJ{IVh%XXS~*z-ga1*wl6qJc{J~`;A$K>S(_PEQX<`E>OgUN)t$1>l8pbw znC_w*rQK34o>Y{>S^m;`kDsrUB|YXjcHMB5aHLA! zJ5a~1>fYtr847nWhVfLwFLChDQt?BR>AK*ra8_c?*$!F_G^O8tO;GqKCWAzUEh6| zxmrM+VJ>^7t8CTlTc=rN?N(hTkWwzJJUnqi@nsN1M&K?eH2|DXA+7Q0pFn2gO>{ zlqN#3>J9&2hc^mXmx^%%XJun?{tf1!3T~Cwfx(MNB^D)j;41Z3DU$1H#>CGOG$-h4-B8bjqo}!J= zne4f*Z8zP3stP@Q*=%onnkGomWb1+756DS7Ff!Y~9-tj+q;{Ba6!P=sUYmiQo+7vn zN$b1(MvvTt%ec>3TYll@jviO5f1@@c5|iR3C>}v|;(NL~i*NU5$;j^X7w+8H5C6HN z`OdcO=ko147rI$jS($ozPtSC}7aOC`41h&`eF2+x-+uvc1!6t>GCs$$@(?=5srO= zk>gg~?e@bPcGK2Jl*0#iO5{*a0au6yY8eL%R)Ra^s}Z=5x8!C7RJ*y-Vf~#DTu$gi z!O(+Q{3(4SIREE>D!v(Vz=Ie>TGCGM{hf6LeJCOQ!O14%210)O2Y*V}1>oX#s2~^c zskC@6jPlRl*?V)o6ltjO%wP5jm!mQt$TAnA>DTrqZ29FlR-UAEDbtyyOGiiP z6H1Qq-<4x5y`iXz_j0|Fu3PQiyK<9^h-h6;>-CeLcdr}>&S-mAt)pIXCUd!uF0`$( zwl#9PWBECLy|ng&xd=sO?(vgQaaH>%)hU(uymXZPB}Ph1rQn6*vhD|}$M-yO?UFL< zQa@iTJI>)3Iv$1#iVIO43lp?t-cLDID0!xoOE%%u6|0O9xr>q_YyYhI!BQ-PhZJR0 zA@Sy(dXLnKH=T6k;OXQn<$P+jN*0~GV=SLl<%S~VDw>;^0pYH3$ybsQKR1^efx-EE z!%-Xd@5`=dxVf=tabHZTE&i-cSsrNPJl3029^rTGX06NH&@=t5)sgKivcjKiKyJBE zwM$ziz3D;p-t@CtRzJ5}=$$0zDt*j~^Y@FX_RP=q#UpXg&U3BecMkF%ymeTa+o}mv z`1;tI#-KetJ>ag(2PXBnWlJ0)l}&z=iQ)L!u*vsXd6>Nv%~h^XHh;vP{9N8?I^xgu zp0&iTniV=pUZ`_iNV$~hv&ocQN&VB4pG)fWtvPdrbJB^RfoWC!O02g{&c^v#cDTkQ zq5kO4^bJ?CNC)AGx{VRa_0%enB)j)m>#Mz%E1C6fC8fmkaj65hJ8DG$;@sf+=S(HPTY*Y9*)n$SJ9A_iF-1UIjz z)Mkk(Qn{v1w-qJp@mh(=WV<|zGOWD#bCQPr2boDkUs5VEaN&NB$uhvXafc>jW+W=Z zsK@)245ry(Pl`;}kGuVcTGr0mrRtQ!W|3d)7nOijAqUDZmij$35WCVMb{1(Kh+Bxz zHX7;ZY-Jk_7gt=Okoypwev(qFUI^l;5!D`ZCkEQBktGp$AUBdZAJN_3QI>937NLC9 zRFodv9w}lR^-LN!MpL7ZzVoeM!K1_ejw#}|rfV#xu}Ix-S6vSk0- z6cHs&%z>cXZEucXg`+t!yNw8pwq50oI}e1DBu&;2A0(VDV{cDqA4F9OWJgKwE78@* zQrv;yrA0Pwsadpx#^<>xJ=gYaZEj4!DaPOV&z+RBE%UD@`w!;^#){io%g;oG&u1g& ziUsW2hQq!Jecn)hQH1pZu&RD}R#X(>)6IuS0a9=csN7kseJn_K5DEzghX%xpuL1yy zrKKr)nCQ89wjuX*<4E+ktG=yz?@KABfkcKm;Z+-|{nC}1BtgS(x4ZcCZM~lq^6j*( z;mEBzt)99*w0&2hv_W3J@x>aK?T-{iyj7K{(ru&TRz{l`{)HYa7=>#qs7d%rcY5Db z%eI(*3Maqz`r)AgnaZc`m9Vj)r>!YH0vvVAAJJu6T7T^)5JZ)uc8bWg_)Q3~>CK~d zu9hn8HTo?MmRd*X6lr)ytan8|731IBQaU1-5VtrSZf&qMS3h_ku$)Isy*FrAbNA?+r zfPMc1+>+W4X7x=2cYJoQR!D9KdH0K+ z@*Q4pmIs%^5P)HImFu(8^3GKEtZ*=k^*4^BVp7kx7ud}lr3zGbDf@zaBY`67xW^N= zlq>la%gsIyTzy8Ln>R`PphTTpJ5oJbbGFVG)9>mJ~SzJ^)GTjy&j}sTx zac*au{z0m6OPIXbRCTt<1#9RJY7lduaIvW=1D*9+UNoaR>$BWUi1=5|p0;^XntF6B zWrBpR7b=V~lp<)UZd$2tW8l1SR9Afac}zD?t}yJn zNX23wF15@l*6uBmhsldMxZgdCqkR(vb3`hpZn~OhPs>T81FRgNeir+mg}*k|DWupVngn@Sy3nE3*u=KrYjZl|8*jcu~>OGq&f2;nbMa z0it+l{5gt$ui+UUk-{e3|q896j9SjIr-( zP|=CB9Ng2v(R69Tok;kK%}mLYJ?VQ7=6~tuG~~>-1?p7Jou3`CEqKQss}%5F_L+OU z`$#X(rblB=^_oP&2dU+|@B2?^)b~t_$GMf#@zA2*j1o8WR9Z0@PFh(A#f75d9(~UK zAZ}5ycUs$hETgVucmJ50xYIgeLy|8ixJ=Nw_oP-}>dT_N?W%WasLuN{0g-)`w%n@~ zNI=d=_ViKfWdCE^^TeDmhoHUO&`%1#utl#2-6d8v^~CYY*T}lHI_aDXxwSaAlXQ|{ zO?6_~geg`+6xBXfio-)+_FvPh?>SeBY&-4d`pKA}Z|t$(dXU!Zir+yjNT#tGqSyP|Cf-bXkzk%vVj*mzn)gs$k}N?>$z&>+SreYi3ad zg9FQfI!QZ^!s@?uKM?MY&F;zF$+K`yo+IcPcsyIhW#6Cln5x#9F$lYvZO&*>?5Dd< zHuKM(+W8m6fy8Tk7ubYLrkCBUJ~BVlyft8P=4rt#Q-PX3_yLRF?%s zn~Sb_Z9jOu3)P0HmG8ACc~8yUioH~SYjEE6kyLWeBA-bQBL}e&)xJ^GitD=0pG-m5 zB7;Y0Dc&aQTLNSUkDg6U6f!(_-irSv%UG@B-%7Geob*8W1KGw6f8w@|2*r0v;@NHy zYd-Vu>p2C!@AhwhF}csxO+R|7_Z!3awKO6BcDK$M*C(DDram=dvz|JuSK(W@6eBY< zQ-WK^Ndq1Bs-E7FM;G1qp&J&gph^%U9M%11kNe8cv(Xem;bbyB)2UBAWpUh(WzH70 z1#?*Ggly_pvl0^uRAalPx(9!gd>)uwxqe%1Xu)+K<7M-s@swmo>x`J#>dEiERn|ug zc@yluQ}#^~`PRz|AwRIOsp_tn6{gfLWW{ok2%nx-_f-oz)=MLxqxc)J#{u~`;sXMB z7|xP{K1fL+u}y~`z+8rh;(o!R)x0*_Vht$xsJBscjM;^r# zJE&I$OGgo1#>JFGy2rn^id?YO|1vJ^C34iq$0bggpj$?oCncKUQgkTbk`|>@WehQ^ z4P3~9m1GOrJOnvL#=G6xOz1Djgk6Zt763yV+bPcjP!=S2rx}5C50Nul9m3o_QB!L! zJK~I<-N2HBw49u)vJ=tZ%jXALf-cv3JL-Ujm&LSPLWCe+0h(qge#$YqA<8r#PVXa} za`czl_{7;~5pQ@fY{-K_XTwkjETz!T-NRS>%A`tCB-3(8w>$`Euz!Zci$ho|(&d`D z&K1HllrHTebS%k0*G95JBuI|&)Y0c;o(b*amBuf$0p-n2BY00s=)M^S2F4RMXlPZq z1+%E*uqa#7zdM0~DT(2wH-Sz-@^> zhVE-inq=6L#hRSXT3c>@z66-nTMTfGSF=w9iAClp8h8Cr z_Mdq{?DFi?Q23Sf8em&v)54a5$1L>~u7SHJJ7Sh=tGJ=)1@*g%duduPX)0Tz!gQJH z12w)?5e9RdP;I=PtPM6=T|0?&*UK9raK5QwywU8p8_6zz|5+W+szxBa!iCnD*T~2d zERBO5(xCZltCrC}e@vJ{v7%0jH@L4sn3`Q6Y@4h_$)W1ner&inKNG-RJ~fy8!;$eV zS5F3yn@FnHeNM04wGXYoHCj|1M9MtpG}tCNS2SAsHS*}4Mbb;llQ!sfZ)05lx_yLd zSa7P~%)0qdd-;x6yg|ryTxMyj<4gJKk?k6SH|yVYYzz#@<63O2=0!32o0v1n$VJ6p z7L6(zY)a!-eqvYrmI)XI4Vx`iSdVcT@tkosI7V@|d(ghFrUnu$(qJqS>Mk}DokJNA20HP`0WIZD5H1|^OtN(H&v-6+$H)8ElzHInl3@E(tV)~JO!S5ZF2veS zrnc^*N11!ElVBZKHT{X*={Vo%s4Vl;Jd`#+ZZyOmaJigH;8jQPyDpW70FCL{=*^t7 zvC9Ti&roZMck?5DYIIY6cq&>uylwX;c*kzjLkmqZ^f2a5!{U%dt%HruUO!QBGITRC z#$J9Xqt32zYU|jMd}CZ>JR$$kdRvXVII&%<&S3VJvUY)g{lWOxtpf@UqK$`NNBzUn zriC{OKF+qO0VhM}4v;VrcROeYoM~JFQX@iK0SOiY?*KDJ(bVj%sF2d}b=y?~Oqyw3 zmN%&?oM#opWf#KOW2@eQj%!T6>Zh)t1&i^={iM21E5gWiR2^iJ_19reEs6eZ9IFCwKye;NpN=14F62jhR=T#<`s!u8r96_O}?(|qat zk5`I<+`ipf#e4QiGQWtDJ&6As>B~OtPm<*!lPDT$8N_oLjiyPBep_HJjCV{L za#FuD_X)JuxunzUV>n1hTkyQ9O+zFTgp4)dbc9$CWGQ|K0#-J^d~h20ZTuYzPr(L$ zY88LJb}lVp$pOI*8Bqz;QN^MRFJwS5OfmrjkAaafFk(Z?9*~vBPyoU|GJ#HT>)TBk zx$QLFipP&wzuc|fnwPvsMZ_kYpRyDvaH~bgyv$l&HRbTR=OUGtj$j#a&e@yL$4n{& zLHyS&TV7k)Ut8a~HsKkWIWvp#{t*$k^yHQBWo8l9C+zvb#uUr`PG-=z{uPz<+CmbQ zMY~f@qkx&FRP+9uI+PQKWZAO#x>bXzw@hx%>+$0v@}ZMRBuNyt(x-9qez$7W=mrIB z>4iI^T?$puWED|QbpKviDSzl`S;NIP)&&n%r}ATR8zx}r(0r+}ke#s| zr=<$45nL(lzL79=(Seykd^dRr;RL*IbqkCaz{U3HN)+>S>jg_h(`VFQZdsWYC(X; zX8M`>lJ@M&OKWL7Z#Ig2`rJ-b)SkStpWNn$9L%Qvnczt(ed}ra?1BAGvA+Ih$-6!J z3x(wK2XXno?6=1^e&1oxUh_kRz=+;fgqm{i(mXn5+{p{Q63?pN^ZLppcrK1A;?caCY%{_23|sCkq3&j+OjurrWNsWo5@=-Pm<#!sL4;zum&IN31W3j&g6uRlX|8|S z#U9ojGXSo1knvmC>elJtJ`3=c6zu1u%x0uy{0%)=Ub{KWq&Xgt_x+vK_EaKFL39-R z=nr~nW%cRBzSGD2?=LvZ62{Pv=+62B>?E(=#j-day1acPG+9tEzR2fVReGteInR8@ zVVuqFcd;d@xh7BLuc}}T{i?WUbxaDETh_$2E(H4)#&4Bhjb1hBaks=NXVkH7GhHeB zKI3%pvK&2opGkcxV?V7Y{AYjNT2jC=RiS!PWu9tT|J>SljbjTv!n&1Pc$A(3SIftf zubn1_T^A71xaX$U$0|gubMWW;mRiY}5g|`uLtX25{Xuyv!TLyUMWPk1U`NlGk9NgSZ_PtFxio28F@Hg>ry>jE@!G5en;jCSSVbS*sU4%;cf-eXBWYhDXdouYU-R!JE* zzE;*|X=;D?s0_FK;}pfFr6*mr&7Md3vFmvzC2BJ2pI2ks-Ir_6>3I*v&nW|xa9#ZIQD zxZsw@ESs~z&z)3i#t>qj#iZ{%b)%BXpN~8@3do;rClqh*z4ydDOpxv|_v<;IRJ~!< z@F`aCkKkd_=f$h#elFLOcU#|2G75jM_#D3VIDEO&v6g*$m8|{s@P5y@^W?F*cn_)O zO@~^ShMm7K3gPj3caDAeSrqR1+}76k690)hE9+r8{r-w<>PXT3pJHOImO|5g);0V1 zgmuQM_J{U8%;WNfY9As+cw-sp1Cg{zm&?(ha^70z5KWf&72nrt#8TaTZPgZ4%M9`I}4`TqbtJS~3QR32f`?HKU< zBzmpBX&v{gmr{mJJ)KcA@ z0uhBdPrBaO-Vw?=qwoVN^uZDg?nPRPcaFMdBSpXzxHs%G%KBYUkTt(7?eEh!%W3*$ zRbJlH&C2R>GQGX`F`;~4wrhQBCZ~V%ng$l&hh5LL76+KaTF_)JrK{2yeSWE z)xB&P_4;uzqrr1`$2J&Gh^v_+l1 zEqJVTA5K!KN(+{6L9IL$aUT5%*(=)zBA*@cU)NlJS6H+k*DbEDJ(p%?l|6L z-GCoUx($#YI5IU$zUCe1GaBvM@DM zX1ur3f4m@FM6I`|@Z3>A?O@${N{N&mH7C35>1xkQ$wD3W#1lB@d+#}nE$h^DlS$=P*=}aJSM8&K}R>m}sA~z0_CYx4Qe|KHJg!1jotZYn? z(Q+*&;bX;xL-nt*V98jr^NqLF5dQQNiQud^2x5vIpMJ?4DL0k$yG+n?bj;6@8sNZP zqlRQjN-L-N6ZIDAXBFpsp2vr3W$}Uux7LdtJZGH963U%I_sfB&{IJ#W=?A(b?>s(d z`^t{Bte~CGzP>w-g90DE%)=WEM31Rr8c2aUKf{Q<=M zADLlpQyFb_r*c}1iX#u>Tz^%5>Z!;`5HcAjX2n?JsZ~rPtvT|*#h2B*&13E`-DXqg zGrHSG*K78dlm)IhD#m5`o7Q2@foV*S8M}mz-3?tfPS*E3#)_q;b|e5fI51M&&@kqb zM&Xe9x}>|~tbTIzX0^+cZu#Ry`1ogg9si9Dc2>LY*4ky-P7L)Emnvx|cfvLufxu{< z%wJ!1&yz%4FMTQ&*}FgKcguk)dVcE0R5C@ZsnkJAOKulc^tKvv`naRYnS{{!K#& zSxQMv0+Mv_;}t8^uU(@5JJ=9-QECxukAtDp2I+D@@1_m-d}yuaUI4ut)S;$IDUHJh zrZZtZbq$aKL>)Qa=BV%f2LHL$vS>iPv#OBTE_9jp#ydrmiLbgWs5C}Kxr`T1%cSna z;`qUXU+(W>7l;JsrEG;5~@W2c61V|YJwjMzD81DvaUaF!|Ng)M3rTEC21aQDCcSXK2NnZ_~)ZsGJW zZ)IO*0}}ySX~D;C4km(Anso(2fQo^p|2AlqTrx^c-*KAVa0L@MPFt8&Ll3P+kR=_5 zgDw{7_ERJFyLZc(#lh|tEMhT1XfJ^mVA2fKH7U4zU_19xu)hXjV{lmfV%rANn9G0h zqmH)*Chx1Z5Jr_}<1)bbPWYb^oi*``ovPXRXazB9@y0RZ(O$E;wM&lg@9SNYv{qEh z?3+usgX}9c7idVR0qiaoL%7Eq7PN@PGUFmwkr)wb$))mWw@Q zM~ONS!pySuh79m2JB!Ct!KV#X7Ch_c@_hJ9>#kL?u`avw*zWr$HvH;R!-nfcq{+kO zZu{kD;uja!b!&>Ul+^_jeWskb>(y9#vwxn&_vdm)sGUVka@s)sf))CvevQZXbMLM? z^9I;)}vQTyriK5r3IQjx~WPt<4d%)!^u@u|{c=%kf^DfAeh~J9 z|4em<%|>-p_sgrTBWk|~L)g%oZp{)T)YHK>HS}lr)2}0McmAYhNh=ZxsEX#hq{(Lm z5^V|W`YDW3yJWh&H$Stgv``Vrk{6jru>SPrXE;V}@xs*|V}0VnSHbYyHRlJ7lm3H? zo8xf2)q zW0&Txi|N;zH`(s5Pq^MRH|^^*rbZNTu-=ra1g6yM3|U)GpUK>_MXX=YALB7tG-BQt zzF$vwCw$E_+}VH}$W@h3KiBMY9w#=V_-neuK9uUnv1tyLwQs37!1|p0AyIwcTDZ$d zgA3k+SGKL$an9WMCJ0~l)-|)|X2w9Z(<~!Sm;QQ=Y6F(0Ty&{1em^K`@7AeFssBs( zjj}}-Al1qNvx+jHld;;E&-pmh29T>IR)OIueIQHG2WEnT%yO8;KzY6lNC2$^y+`3D zzot=grn7V#4cgCJ)t+-^U?fxt#4NUjv-x_e7DpY90^*j7Ux{1R%@%M>!)Rw?ly}fIf(Vw&)-;m;o&q zf|UbOMunh2Ka_n3Hlx0kcE6zDW@WL@pM7msm4Y#Cx4dk$mMlOWV+2lryo)bt*l<{G zF_m2){-bmHNAtd$zEgC*Z@dYd!dFH+So+s~#P4PK;tIs$xuu;wR}t2OqztJN*@_fH z2{_aCmg>bgN-V2wtR9HSHx32J&o8CPNl7z$?qPG}YrzqbA5?pJc}079&dX#l3SV{@5S#3R;xb|?td%liVF(TZ<_nk`-g_;Pu`sYWTxS$ z3m*(x_<#|Mq&IX$cBxyQkFsF8K%d~T8dqVlpaNC@nf`ttkuB_TumcduEKc-h!T}*N ze!y=$*f9-q-$$83@M7Ya`r<%S_)EZ852%WC78{&ns>h+lYL*%gMFk?#lngeILj)AN{tT33-(WS zN1gZjbTo4|#`ae_x$nE9H)LK5`m2siQP~lo6RYWaj2_$jm{z=RR9&@nUULxN?}55m z`P4r5sj*K|z2ug9nDrqRqYZG~{dEyHiua zTdNFY;vSoJVafKYb~1D27$->DPJGJYo!GU*3E5Gy<0LqJc11L4 z?PN&D>9+cAz_S-G<6Ak}ZMnrL%bx5)`xsmevq7!Lja7?|@dp zi9%IHsGB-qLGAEH=j{Pw;D7=Q4a^p=0>}Df8A#R`fNpNcW4CZ;5O!qvH>KpGGY}ep zhPs$dwtm3eIRrQzAB!Fk(8LXb42}ZT>QJ^Nx5%6n7t#7YiO3k2fcbedz~J!>3lSL^ zSu%;e_1^tPz>hp%k+E^3aPwUL+sN+3)ems-;Ed*L7{7o2{uldi#`yN(>1jvrEaLF9 z=z?>Xi;t-yrd@7UoVPR%qoyl5M1MB~B;nNhyv3dw4&z!q%@g+7S;Q%WcoX6femk~* zk3`7XN%Wi(D}%@|nTLbrPdc&vo$}hcOlr&GVhZR6{|VR)6TQ|8^}vZdYG?zXCJA(5 z4s3K5*#l~y$Mpc+mg1mD3qptphcC6L&z`;e_%Q;Q_I#P!*`y*n2Zwa6jedU(wfvvu zg9C8lwq{-TKzf7qRaR`}v)9yC+hgSBwxxUf`&R%keH4%Zu}Kb)5>-@7V6&726uI#% zrc;Huw{+;L&AO7->kA(SIg|yrWl4V4lqc(s&cEo4p>ND9vI=>Vl{19=XDEmIXAQ2y z;eujL?&NkWl;V=+S+Xj7P6w6Nr>jWM@}C%j^ZS4zNd!R20bya3fFA{%(DRJZo)Yc$ zNBsv#s{1)EAkZQQn(}hR8p&XeVc$S>9rTCF<$e=@x;;t|c$3y4nOm1m|K1{;DEqVZ zZ6ptlaa>op)V-kmIzZAd-La!n!;e0*5bw58(Cl}?EEHPqbfg1vQ$bJ-0{ppP`wIo5 zL&{xyOU@mCN*cJ@IZ4tu6|@q#0M2m%RW-an7n_ zso@0?!QSNNXYZFjZOg?RPI=?oBZ(W?EI7~E+1a%W4Iig=IS4)RfB_N^PA-?$`{fuE zJ2HqJDl(?MN7Nb+fkCcbxMs}Mf9J(Me(^pYDN4;}g1|@I)pg#Du$2+LF%d3V432$0 z&9+wv7J)8VyPOm>#6sLy54UjlLj0zt$yB^n52DHi{Kf0t-w)H0Dcrq}q7Q&_#AqV- zC77jQ2*G0kQ*7SuH|M25w+g5P|ERC$dK5PT#eflu)oh?up$+8dgzr}ffSxXxxn(sE z!e%f4@PeM9q3Rs9LP5_@lvlY*rRjq+Wf8Hlk1zrp9GsKOq7U|W=>CC2FXWBjQ|rjb z9ct;y(=@Ww!D8iv`|kDgTJ`&dh9|v}SkIh{EoI0$&(w=Nm}TA zF{rmh0Oj650EqekO92AHt$+!_P91kfQ8os*MKLltc@Q8fvtU4bb2zoTyW0-{DIaw@ z{PPuF(=h;GMf>V_9gJp<=Sq`4jwUCtm}V26r}p*^y`!UxKG}@81e+IRWcQ5qa^$8^rQBj{PEa>fbCPp0=t}Ln<*vKHXKQUGf zW;uOA*Vv5kxaJ)MawEQ2iO%m#EKlY^&)ppzo4Y4kU`T0G`)_X7S#K@L4sQRs+5L9` zaa3mvoocR1B{eWEYMJv1acL~zbh>>|v5m&FU(iqE&~kd*vP()zUS3`r)%Qh_oN?b? zk^6dk{?^Mcg$Of>d=Jvz8HeMXd-C-8^EBB_`kK00Q$JL?&ZnF_*Kzyo^tX_YA@8@H_4M0jKf%9l zZ#c40`t`#Oyz|Nh3vA}6?~#)6o_C>%xQf^$RtncP-@RDSdIzT^Z2%@{L0gero{Y~Q zdCL&bTd@B6q!Cf>z+s(Ei!o?!6G>X92 zY{N6Aa|Gu!JC(BsQK*v>i~Ev0usqSB ze_H%WOZos{_5;#3fY~WLY7lHI|Np{1l`a5$ih!Nf+R>5WVr*D&o^C*38SomS5p(wZ zYWM49mT)&=#sS6O4|s!FDfTn7v$}>kL$CJ^4!&A7x=f%O`(woJ{SZR#nW;p+ z={uJzfEC0;`X`*_Z;jxdrHyOb9k+ce=iub(#;3kBqW~A29#B(*I!c;Cp$aC# zzrK<-P>6{Iy%5@#mQvtGs8|s6$JZjP8SL%d5O2ek1axo_5$Q*h~h67T@=H})o?|*#^Tz1(oaGhX@zaA?3 z+hiu!PirxUCr3+YXb?dpLqlt7>gIw+i%5$iNBwmYJe3s#$Me#Jav174M#v$wee$3b z30PRuRVq#73RUExbpKvXWp&+HZ~u@r?yQ_ zMvF#MOaB%`1OZ8Cwy|kzZG~&pV2BJv{eLDx(qaBt8Vj_{0FhsSw?sro3j?Bk zG&D32XTV8GNf8hdR_3Ds8%M^3ym^QRJs-fe0|5Y_h~x#hFu@xG-!XjskK_HUN#3&K zJayp#$C!aa*Y@^;6BF_2>FMWw1Jmq_NAUXB`TVn>Xuqdf|Fu;AoN*1$SBTR8dH4Wh zTJFglH(UO|DD{6{m4EDhT_k7x_06S;=xc}qR%aRDYYP6HA(8l>3;53g{qaG}3S!)3 zNk7RPq2g&MZ59fGCJV$2?RsN#({{rQ(>e!}-HkRT^Mr~_{Y#hD2NOkbrT+6Y!7;4~ zhmxhbMqAH=yRa0Ge5HQpz!$n`yfGEZ@FX_ zC(Uz1_V!LOZ@~ro_aXgl6k6LuSm_S3B>7(e?_G?8K+gy_VV1mA^MAdbqXa~32Wugw<9;=$h=W;%lLNS<(^gkkG5rLQ_IrYRt1^bbi^6u%m7-FE5!*J@Z} zLz@k;yTgb^Sy4#>t#7wpp2KFd%;{y13^5t;LWKMHu~8tKo0}&We5zlEdrA%-Q^xp8-v~Y&QYkZ6eAkcIF_bbv^G>wjZ&@+sPj`#jf7FwV=xUo<9-kn;9BB#38 z;N;qqBROyX)#{X8BP`k!Xv~I=DluoPnjw|^d)ao!U9GPJcfOby7>foKay!@=))9)K z8PcO0Hr%n@!p{k2R3u`ke_etmvz?x-CTjU^<5$L=!O zRb0js{`I&NVa)t9hiqv!adgt2xk_=D)e%;XtWCur#p|QIU2hr)VrDmN?Ta|3vX^d_ z79ML+h~MBr5qEZnJBPDuc{aAgoI~Lc@d#Z9On25-R_!^~VmtEIQ=x5EM+l?Hx;0VA zHCGr)ls^+XgW-EP@r7iNoaE5Epp7L9;VwV6?sixSXb@$KrOl~1l!}!PgH0GMw}Y(Pt3D&O5P* zBf0T%xgi2>;cI#L7KI4bllI|c4+z6EZ2F_)4ShpmM>rXoKvwFysFpsE(=w39sIIy7 zSpqo?OILJW(Rx#y<^mzHS+nP*M4lN8Su^v(T_a{Q*1>bQ?TZ9$N#;JK`9@Ca136*t z_z4{+Lf)WrY5tY{6)#j~(S>i0`-YZ;{5E7DaG_cDsXFpmrU9d8jG+QR6)VD!i>(3hzmp zhFZuaErK@QE!%1`sIcWrnR|-Rr-;708~Ykc<~)`rz#aSW-OXv%5QM>(wN z=`D|6R*p50fVUzE5c;*5JD*Ln&*_kE98PEmj;sIWUA-XFLEg^OEF9hXVtxX80#XiS zHB-Ma+T61J+af%}cg^cd2&4|JJkE9CLnkWN{(hHL<90`j^$h{!Bea?Fz@n%MI?UI)foS@bS;A12<5J)UHCz{y+1(jB=8NS87mUXGpE6W* z39?kN?8(yc*%xwjR~G{_opnp+5dql0@BGFy%x$SP7CU=0$s{)>GnLcKPiHWy6NK@l z;zfNGvn=wpCPsEAhqKmMmfr{_`VnWQtiu%j{%9O@-tU)xWV$jwz$W0aOY0zaS+dw+ zGYj_4$Z)U^Qs=5NN$l$!X@$48vjY(~_ZoSMtF4Obe%fW^& zwxEALBU$n)rj}wBD+|2Ix4g`;CIjs1a%)#=c8;|#)b+9Sn|4K9_vWrgR+sG)*5gH1 z=G?bGPzvzHwK6PD-RtP0A*&Bsj_Jny7SAZrMQkZ5TO5R6)%R6SoY9Gye-V4qlA~;E z?~3Tb&AunhIgcG&or6zwAChM(S~u9oBB7xc$mnzP$7lCSo!~2C_qDroy6%2{l&2&K zmB8H{ytj~5C2~DAozWWvE8j?K6P3el`1&4rHzJoG-#pp&PPI1we$JwvJ09amTC7PT ztsQc@F}jCrrgKD~&Mb)}ej`>}Xvm!|;_-lVUs#Jrem7g2$BlqA;K^18^32pr=P0A9 z!L|R!sT`)gK=3S_6-kLiU!0rfry3&9>&=9)-+UY2fGOHs8G?V*^5;{m(A;mOnDj++ znp;yO)R@T-6IpfCv9dk<43QGg++zpu>@*$8O zggYs4eR_0S55IlS@aHR+zAuDyd$18PIUZS~N=HP9@?-arT~E*6+E%?AOu-e+Rs3U& zwzMk7ze#RkaJK6C^`qcmQ88x1ZL-RNB22gut+AG`Ba}2N4*pVTRbWV-jSg?D+tpSVShg9T!FPgC0 z3R8O22g$Zl56x@GB8lGGYy+yj`+J&ndhn4M+js?^7b2?%48F=yI7pyS)T`5G*kw6$U^T(kmYiB^e+`B0@vDt z%iD!S=kJU@nY5xWFB=qI=P4<>+ij< z*E=C%A)F3Rg#R0^3JDjS2phk$I8d7^Q0a-V%syEdb65M=&1I{5>1xmHEE%#r(&W&) z*|D(jr}$koH9S_hYTFXNmr3P>_{xB%a=8`h=nY%B_7##Oe7Hagl`|XclK9q|9l1L^ zg&WJR(hN$IB<7XrseE!HbARbh&nGOtd9lzrP-@oMUr&8eX;x^Cl;+&es`%pmewqxv zCg}^(2j&9JusMNBIG~S2axn4rvC{C_04Y$%c^0HEkI}j?XEK^2n@d0KEC zSQw+EdW72&i)KmLThDm*$B5!$aENTU_l1Z%2*oTn^jw6Wz&yPY$UB~hrNXJT9IcPf zVxSiN_IApyOn{m848c(v?iI!G#^Vnr_^&6?Qqyv9Tvp`3UeV>r=_M-S zMmqmksE;@*h-=RyyZvst@;a+)m_u` z?Sif!%fVFjGj>h;Y{%`y$c3I_JKWqqZcGI==0AIAHZ5RURoOav2a7+S$Zqd<&(md2 z*3G$bvg>KT+$t>ZsRZ~Rd+ZfeQh-=zZw_9OUN~0c_vWh9cf}pe>LdWt9!qT^CBJIO z8U&ZF@dlk*zAQrz62uj1f9N=UkZd+nk@BjP^2_j-*#8dkYbXNK!&80@1zIAwPAj(=bN%Tzh zPwUbTIZ2qxP=qC~_Rs(oKqwPo22v~amLBADN{I&O(FC`RtY4F4$0hRQS{KGlHe~{r z8LW&QGZP9`8WBl45il6`ufM+d%;_^ysR(WrnPBUDiSm+|3FCjn z@aSL0^?HeA-usPDo$U~WG(4gWeS-~p{9jg}e5)@AdrkeVy4M{6X(HPo!=fUuxQarv z;kh+FFpF<3y^|moPn^BA2wWxBWJ@G|C#AiqH#c>qH%13#HpF(7&U^PQT>A8a`7R+8 zZhxCghZ!C@Ol$eD+Ud8VEjQdA&FTsyhcq^SbH?f?-^S2}pJkJw$TNOs{HFLph4H1Z z{A4j?hTEN~F6j6RMJeJZFqrsSA0&?~xpC}MXWI1cHr73k3zxlt9v2rErw^aPpJkY* z#ElK+s_*1sp#{qQ=ljNZaD6I-{%c#Rv7pqE!nnFH_<;C5i=g7alZ*K$&**KB4^hfa zHJEpJqR<3PSc{W`@QW-g*wtAKV*2idUlv?(CFr^3j+Zc=iHotsVo6$R_DL<7ljUti z6-?)PiAnGJ(?fEFlOeL7IM{q5{W3TrU7|nscgcQ&i6Xu&32;7u3T`;NTAPYb3-IJ^ zXX1YAV`L5H_`C6BMtAe+w?wpzMIHY$o!&MUYpbrwP9mEO4ovuE5iKwLZ!h>fy|9Lo zs0zl-J|rtrQgVGr82&DwHaj1ckCdoxI+2aZ-$ym{H{p6!$_lfE7m^yt|4j=EO9?tiJgNEmw#N z_ejh$laO82lqfHHN=I9iEy?}4m7Sfwq6IGUOPYU{u}@+@ZEk+LfJ0eX`L@qEU^?gqnav~(`D!W8=oa8 zxw$r13_CJUZdMiQCM@$rWuDRGQlT5bXkbF&f4r@Y{kwAnATdx=S10=Bf0E+)XGwvm z_c0NPT(9Bi4|E^yW!3ry$Y_`%3kI-;_Lh1M*u7LPYb_JMEWllQhd9fUz%gRME#}}&11Hh>im`MELtZxIiJfn^A!O{4alY^ zy|UD!W9;@F*OwW*lKt3xnMMg_?~xzO6uq0H@y=HR&`b`oTj*=>!>Uf(L**nbmwKkW z4SQ_!2k)d#saY>oxea&hJYo!*&cmI3*N`PzmkivUD~wBDs?i)cIb~a2FFRCO%;zF` zE|}OpypoE>xTO=I8p<-&Cw`7CWj(*6CR59Z&L?{fcDTXTrH47s2)NrX7e(B&)ok`A z$TH*2NXFaSdyC~^j*E!{pwj?uYq5~&%p0b?dB9^fcN;c%P3qVDGs7F+(_*G$@y;hw zq`t21@Hia%1I~+qxHCk^J1jT5b1_P#$#rDPuhuy}*2B&uOAb5sE|YxyU5i18 z#bO1DN0Udy-GAK&7SC+o9L9Gr?ah}f{sXf5CoWqI1vlV_-C1xO9IURrNoPMlN8^4N zqnX>t|3VHJ5NDI;!_OHeR=-%|w(u{`?%!6LkWw-g;0?}$KrV~n_q~bn_OTZ5vN>ae z@M`zZdin>lASI4=?MHY&qFHx2^T=a@)>OP@Q<8+qj{Xn)%H@h8!!M@2D)3cnr|3bCXxt(fUM=HhGsNf%Q zwOhY~jh2}Or#;6tMq6y+YK+d(^774(9A8cCdLus0H`O-ARBYlKe>V!9#d^GldsES|Z$p`N?; z;LKVQ>~~QtCVtTK+M$dsCb2#;MB*$fA{EqzuKYPkkzl2ZuaK>D;*< zLdXgvc4Z1xW7O2tAU!>_2j>L;#B3yeF;})ZSGKv2@mtQZmE&f6?}P4mojmK(QIx@K zjl*l=TNqCwY{o+I{QO)z^<(^?XVFT_kU7CjZO9-12Ct)fSv6f2jRA~}0-KAciljJ% z7W0+f!6f!BZx|G4m3xBoWSvUR;J41$?(!EC1&gOo7P&0T&Wc~eOrI{{Pcfc{C_X~) zYyqv``1g)7<~B^1eH|CHo`^lYe=@^SyRssi*izRzahmtORnr<;TYAwGQoo)0Orb!d zyPJt`b0Gec7?kh9LU;aQ5jpJ)-UQ=fWCdr4ECn%5zQ0X;;mz+0xI@?!;l!V9sn@W! z1Son{Epfq*?(g4sXqWS+@4o`O>96VNC@)Ys@ms&zPrnl~7js+ukO@aW)-#YDWfc z9#qZxXd3y|*_`Xq4Y;!#Es~Bw$6KZ6K%UJw(FdbtQC*sVPr+k+B&JJ(0Ztv0jZIMp z9R`=CT|Nb5H4OSP9dS?9Jl{1X^#AOYg`2@XW22(NzS19+p=i8d_4aLO`@`b-tul}e z*})treI_n{rt2LXT!%6kjyI|rVh)iVANP!!K}%)Jr;lZc$kQ?$^OeV@1QRMDS~KCT z4cvMq5=)!5O&dWRn(gvabYfvY{oqTij*91sOtZ(gx27*pIPJH*!otGV+f5xL(fq;) zNOXo`$&#pwr}HRD(0yLY3BK#C^`;33WaG(uAdvNC-q=f@j%yTV!Z@^icp^2y(;dh` zQ`)c~l%m_W?CKwXf_8#7od&BZ5>u#>wf_itA3P-%Pii4usD~?owFulV z)D=#!E$yDU5Y;r3hv2ayX!XMSogG*8_Dk?>m_*kUj?N9*6JF2E=GE%p#>bPzH8mGV zx1&37)*Uk5sG1vi7~y88fV45+g=vAw@Vlwr`^h%}aUs?kM`7}C`0wQPnTfd%l& z{Zab06jQ7<|MRO{ksOMpB||6?SJ8r6JQZy1&8h=v(~wH8Yekr>-9+jWK(*dvCv=RM zSrg&#phfcj%@0+#2&93#OGWT(UYJs;3n4=T^Aj&$ zk~8HhBe;Wu9pskG6YQBwMY3l4>yScd|HTj%3S>zMQWIFsrn`hA@x{B1)}Rp7aGP$g zX{PR_iDu`upSw152_z6WySic%5MU~CX;ah4OtL=kzH%zJXEha((ii?^DNML^bp5<; z#`14rUh^*llQS68cQ)0`606f3v!Y9!HOdM~&jnMrn(Q8=e==iiROfSdUzU@f^JZls zkkSI@T`^V+!3Rgp)$f7E9cD`{Q|-o1QyNiPA z$fHHsc^0YoTAuCf`OkH>kO);SWF5E97aL7wq8y>1*lo{>LEVKcK5LmxS_Yxy%D?im zY)TxaO!crBf7qd6IB9Fygs{JKjY!EJMqV%E4qM>7H2r{cX|$2!*1Sv!il-<|IrKm{ zpo20=x?jlAIWAVyWi*1s;;vCknPylQDUMhF;{qq&bN;~+P?aLu8Ml^bs4 zW-Kem9}f6Mm!C)k+PzVTX44Lu(F}B43qg(+1o`iHCd{)$7&pq-=f0CO-7OkRuf?m+ zO%@p@n~u0%lBu{v*-8FDK}BzA&v|JMztT~4N0!-LN`2fsc>hXpo+l6$vUG|$g6?QG zoMP^I)Hl*vVKIr>s1YWalM!NkuK~%>LC_lC@a*a9%LZP$roP^~IS=c!ijZrz{^4zW zymAF|^iPkH%G%qL)R=vOVBP^C^b4)l;h--Pjloir)Tg`9#3k%I;1Km)bJhk+j*17# zdHHbM{r8dx`cJ?Qw9nWcfJ~;Y8c#$-BwO5L3GhNuYmEW>`c ziv%Kg!tq|6+M*HiKH=X_<4-Eg7Of|&bT0`ZzjUQIqIFO82-U=<+o*imK6`&b@#daA zRlb?dU{@1=>p@S`L$xWQ`vpp9-*ub!VMx#hMo|8%P0!k#D<8*qh=fxcgSJ`^Az_5m$$5Tv^PMy6Uyt5{X1Cq_FdYCChQc!MftF8LsBn7L-Lr^tYC` zPzX-&=g&=yzNCyIS60UlP981g>|7kbK*_wK!Vb6~=de(dovb?Jz2i>L3O*h3;VP`H`olVVlwLakd97R6}(Vs$iNVS(>b-z`?T9UXNR8$bl?pFI7O=e&pisrzu~ zrz@ASqO9j8Bag9iH>wCho=gr$V>cF$ln31;dV;cCmWq8 z4^9N|g6_2#9Le2@m2WfU@e?YIg~}D^o;tgH%wJ7@`V7o_-$~FA_-BZYgZq&w+LU_% zBqoCvCXgC!?`ye&v>|QQ-4hO0_sRUL8E&?lwc!v*MN=~(o$7q|sBU+ylk{D;TfMR5 zQp$?@Ve!g8%@Q#w7UfNqcgPvIcT=urx4V{*9Ym-HBgMTdF!Ix_?3iDRb?#iYn}akC zl8H64*5YoSA0L?&*ty2bUAOObH?P?-W=>d;*t{Eqnn`$T;LY3HCf0v%$l3O6?xF1G zAhwYFyeEXU!dY2YCe$;Kh3}wg!4`g2Y44+)Ig&i=^}b7G`v;T~#Y{~=l+=(LUxeQr zA@H>984@owmJGTNK+lm{Z}(qfHyMYg7g%uC?EoX~*Q}!jdW9~woDK)#(A6f=Jbb}$ zd@Bb^u?rOn3Z%Du`(#JGtP+oC?R)Y@4XH$AqBNT<(FVR1br+s=iJSUzgoy%u=OnA_ zzg$~|Hzvr@P4D^&vkjft{=`KPzH7SnZ5PowJpNk+{m6OY6jg=ps1M_1*;*(( zX_w1g{yKJr>h|Wh2MkZ9nTSptg{9g%Wo02(Ee{hCnJvDS5nqn`;gTE)-PLD}Qpef& z@Z>T1OdX0F67xj6mxs0>4CSh^H_I7!NN5`3Nc|m@wArf&xtLtEm%QG#Q96?Yv_8v3( z%ka8jj0@A}-*n<(!Ej4cMh3RD()@)9KUtfLJ35CI3o*cMpu)xiN%|FU?5vh2Bb?YY zTHK`LtTveQXZ?s6pA~MT(pF?=D$ktB5%xxw;?RFZ2%=OzFBC>=q)GdebD0eCi04FY-m%8m zd;TGB#$Qr(qBM%Psr4fwUEB;gPa(K-M$#0?ddUJK6jR<(=92Y72sO!3a>)H07Mn^r zfg@puDQ9{gM-J_37I>R-C33Z2$k@PmW+~(KQ&*J*{~xgVz4BZ_b3kw5XFo;F3=wy! zGhe2M4@eE8ei*S>4!3#nOEhdDmrN)fsS@=EGDFkk^dbF_#fy=uOa`rgV%*=kJ%l7-spl2;1Y-^5;=ZmzG-x>@dSZ@0pNJT{_# z3mH9pQ=Q|Rh*9)KTe%SCTiaH~p%AaLT8!8}aO8^SME6XhXbLAdBh{Uv5WMB=5{C*t z(O@>xJbz8w?#hymL}ixBmLh)?UgE$V$wv7@k%v>`M4v3IKYyyUugvWC2dNv*Pec0i zmq)?zo-M3tb9`}l4&eml1eF@^TizJJq!73?cM_S*2EYGhHFt6o)lRHDq)e3c{&Y@X za}@AH(VaV1zI#0HC2xSe^h3!_Y8$!BEEy64*Dnl?SjWj~MhMFIy}o4(sl;4Z#iCqk zLt}%|8B}M({k8OJ+0F%d4F2bz7;SSBFCfI61no`mCMjzT#e9aR`NfBeT)Hzy!!AT- zwtOJ-hI1+~Txn*`%Zr_@(#_FN3G=LejpXIHzbFQT0PRhY;Yv&fiDP)ZJXwnjCM}x} zH}FYu?{;VgQjSO%k<*P%_-R1bq;gf+A^h0BR#yepV+O7t&scbMpa} zL1>z>Nc^fB-_OR8Vw7(wL-=QDc)5Dw(%Ywsky_emEoo14s+bcRxU>wCUsjITaMT$1b)z(g?}%T(_3F` zEIY1X>8|O?7M3)x27s^lhrw88;{p$<%Uj!Fm5o;3*eE>?$)%l1=lfbiI3wJ-Bui3W zk>csd`1sB+g%iZ3 zJX-T()2L%oWeX;bP;~N$P;3@6hs{sX!1?-_ZZ=kK2<(Gs&_Kg?NvqE$gZ{bOfwP7Q zu~s4+L3|Hl3-sc9+m+psK0l%6Tc4k8xrg$i{A`;moEqUa5qwp~H(n-0P7tE#iDyq< z#lDHDJ|IjZeBQyJBff<8llzWZ_gze>$2i4!S@7&y_s3jCe9kZxud}~i7_Ey=EzK`U z&E|sYl41CzvRo|dzs022mdgpF-+>@CT8hCW52|6~on@_g)^vUWcnw$NXkU~J&NCZv!^?W?zJ zY|BMSEqm8hH*w4%*_}eh`rC|V=_mJ16KBrhV|e++miv3lLG~sS-};I421Cm6EWr^k zszWL%zSIvGti2?F>C$Lk?DVO_sG0nuolcuBObTkaB7Entzh$H` z=chx}L^u+;wLofYtlD4ek5{zg)*MQoyp6pRH2KNJXLYlTjGFMrP08&rv47kt3aY|A zf3wz?FqJOFEc*3%JU-&L9HH`a^jcs1^X%NTKCIoYY{vVn7fwU>GSFYr6n^w*PUy=N z2*XP8a|rwJxA5zyTQzorg#q4}N_6rpuY88H;t1>H)YM^o%SOQbI^qBaRAZdh3LVWh z{6Hd5o=61YeTgsPR}^;KB9y#6-^j+Y%euNQo$*yn%COgx<}eR;;72OFIdpI+otgGZ1zlLTa0g+rg60S$U=+_!>D_n+|}Vhg4Gxz{f{lSaXxjU zJTBBo9?f`m@;8(qpme+1VQvyoE_6jN$KrcuY6?IY9uGl6(v1K{!1R&P)iv7G3;E5P!ck+) zwKkra#cBqgH(f>>6B2rh;f8SyMxbNliSaCb)O8V+nI>~`x8IDxOv>zHERp-o$79p{ zŞ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