From d0191b93b55a735fc1590c54c385bd289a167917 Mon Sep 17 00:00:00 2001 From: rklpoi5678 Date: Mon, 29 Sep 2025 22:20:51 +0900 Subject: [PATCH 01/13] =?UTF-8?q?Refactor:=20=EB=A7=88=EC=9D=B4=EA=B7=B8?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98-=20=ED=94=84=EB=A6=AC=EC=A6=88?= =?UTF-8?q?=EB=A7=88=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=8A=A4=ED=82=A4?= =?UTF-8?q?=EB=A7=88=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 시딩 데이터변경 - config/config.js DB_URI를 postgresql로수정 - .env.exapme예시 postgresql로 수정 --- .env.example | 2 +- package-lock.json | 624 ++++++++++++------ package.json | 25 +- .../migration.sql | 64 ++ prisma/migrations/migration_lock.toml | 3 + prisma/schema.prisma | 54 ++ scripts/seed.js | 80 +++ src/config/config.js | 4 +- src/seed/seed.js | 61 -- 9 files changed, 642 insertions(+), 275 deletions(-) create mode 100644 prisma/migrations/20250929130145_create_user_user_profile_article_comment_tables/migration.sql create mode 100644 prisma/migrations/migration_lock.toml create mode 100644 prisma/schema.prisma create mode 100644 scripts/seed.js delete mode 100644 src/seed/seed.js diff --git a/.env.example b/.env.example index 1ccbba4..7b1ac2f 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,3 @@ NODE_ENV= PORT= -MONGO_URI=mongodb+srv://:@.veiwzrz.mongodb.net/?retryWrites=true&w=majority&appName= \ No newline at end of file +POSTGRESQL_URI=mongodb+srv://:@.veiwzrz.mongodb.net/?retryWrites=true&w=majority&appName= diff --git a/package-lock.json b/package-lock.json index 5a3dce4..59abcac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,23 +9,26 @@ "version": "1.0.0", "license": "MIT", "dependencies": { + "@prisma/client": "^6.16.2", "@swc/cli": "^0.7.8", "@swc/core": "^1.13.5", + "dotenv": "^17.2.2", "express": "^5.1.0", - "mongoose": "^8.18.2", "swagger-autogen": "^2.23.7", "swagger-ui-express": "^5.0.1", "zod": "^4.1.11" }, "devDependencies": { "@eslint/js": "^9.36.0", + "@faker-js/faker": "^10.0.0", "@types/express": "^5.0.3", "@types/node": "^24.5.2", "eslint": "^9.36.0", "husky": "^9.1.7", "lint-staged": "^16.2.0", "nodemon": "^3.1.10", - "prettier": "^3.6.2" + "prettier": "^3.6.2", + "prisma": "^6.16.2" } }, "node_modules/@borewit/text-codec": { @@ -227,6 +230,23 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@faker-js/faker": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-10.0.0.tgz", + "integrity": "sha512-UollFEUkVXutsaP+Vndjxar40Gs5JL2HeLcl8xO1QAjJgOdhc3OmBFWyEylS+RddWaaBiAzH+5/17PLQJwDiLw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/fakerjs" + } + ], + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.13.0 || ^23.5.0 || >=24.0.0", + "npm": ">=10" + } + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -279,15 +299,6 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@mongodb-js/saslprep": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.3.0.tgz", - "integrity": "sha512-zlayKCsIjYb7/IdfqxorK5+xUMyi4vOKcFy10wKJYc63NSdKI8mNME+uJqfatkPmOSMMUiojrL58IePKBm3gvQ==", - "license": "MIT", - "dependencies": { - "sparse-bitfield": "^3.0.3" - } - }, "node_modules/@napi-rs/nice": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.1.1.tgz", @@ -593,6 +604,91 @@ "node": ">= 10" } }, + "node_modules/@prisma/client": { + "version": "6.16.2", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.16.2.tgz", + "integrity": "sha512-E00PxBcalMfYO/TWnXobBVUai6eW/g5OsifWQsQDzJYm7yaY+IRLo7ZLsaefi0QkTpxfuhFcQ/w180i6kX3iJw==", + "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.16.2", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.16.2.tgz", + "integrity": "sha512-mKXSUrcqXj0LXWPmJsK2s3p9PN+aoAbyMx7m5E1v1FufofR1ZpPoIArjjzOIm+bJRLLvYftoNYLx1tbHgF9/yg==", + "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.16.2", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.16.2.tgz", + "integrity": "sha512-bo4/gA/HVV6u8YK2uY6glhNsJ7r+k/i5iQ9ny/3q5bt9ijCj7WMPUwfTKPvtEgLP+/r26Z686ly11hhcLiQ8zA==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "6.16.2", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.16.2.tgz", + "integrity": "sha512-7yf3AjfPUgsg/l7JSu1iEhsmZZ/YE00yURPjTikqm2z4btM0bCl2coFtTGfeSOWbQMmq45Jab+53yGUIAT1sjA==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.16.2", + "@prisma/engines-version": "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43", + "@prisma/fetch-engine": "6.16.2", + "@prisma/get-platform": "6.16.2" + } + }, + "node_modules/@prisma/engines-version": { + "version": "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43.tgz", + "integrity": "sha512-ThvlDaKIVrnrv97ujNFDYiQbeMQpLa0O86HFA2mNoip4mtFqM7U5GSz2ie1i2xByZtvPztJlNRgPsXGeM/kqAA==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "6.16.2", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.16.2.tgz", + "integrity": "sha512-wPnZ8DMRqpgzye758ZvfAMiNJRuYpz+rhgEBZi60ZqDIgOU2694oJxiuu3GKFeYeR/hXxso4/2oBC243t/whxQ==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.16.2", + "@prisma/engines-version": "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43", + "@prisma/get-platform": "6.16.2" + } + }, + "node_modules/@prisma/get-platform": { + "version": "6.16.2", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.16.2.tgz", + "integrity": "sha512-U/P36Uke5wS7r1+omtAgJpEB94tlT4SdlgaeTc6HVTTT93pXj7zZ+B/cZnmnvjcNPfWddgoDx8RLjmQwqGDYyA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.16.2" + } + }, "node_modules/@scarf/scarf": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", @@ -612,6 +708,13 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "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/@swc/cli": { "version": "0.7.8", "resolved": "https://registry.npmjs.org/@swc/cli/-/cli-0.7.8.tgz", @@ -1022,21 +1125,6 @@ "@types/send": "*" } }, - "node_modules/@types/webidl-conversions": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", - "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", - "license": "MIT" - }, - "node_modules/@types/whatwg-url": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", - "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", - "license": "MIT", - "dependencies": { - "@types/webidl-conversions": "*" - } - }, "node_modules/@xhmikosr/archive-type": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@xhmikosr/archive-type/-/archive-type-7.1.0.tgz", @@ -1457,15 +1545,6 @@ "node": ">=8" } }, - "node_modules/bson": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", - "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", - "license": "Apache-2.0", - "engines": { - "node": ">=16.20.1" - } - }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -1508,6 +1587,48 @@ "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/cacheable-lookup": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", @@ -1595,9 +1716,8 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "devOptional": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { "readdirp": "^4.0.1" }, @@ -1608,6 +1728,16 @@ "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/cli-cursor": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", @@ -1683,6 +1813,23 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, + "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": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -1796,6 +1943,16 @@ "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/defaults": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/defaults/-/defaults-2.0.2.tgz", @@ -1817,6 +1974,13 @@ "node": ">=10" } }, + "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", @@ -1826,6 +1990,25 @@ "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", @@ -1846,6 +2029,17 @@ "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/emoji-regex": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", @@ -1853,6 +2047,16 @@ "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", @@ -2205,6 +2409,13 @@ "node": ">= 0.6" } }, + "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/ext-list": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", @@ -2230,6 +2441,29 @@ "node": ">=4" } }, + "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-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2523,6 +2757,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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", @@ -2944,6 +3196,16 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "license": "ISC" }, + "node_modules/jiti": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.0.tgz", + "integrity": "sha512-VXe6RjJkBPj0ohtqaO8vSWP3ZhAKo66fKrFNCll4BTcwljPLz03pCbaNKfzGP5MbrCYcbJ7v0nOYYwUzTEIdXQ==", + "devOptional": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2989,15 +3251,6 @@ "node": ">=6" } }, - "node_modules/kareem": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", - "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", - "license": "Apache-2.0", - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -3156,12 +3409,6 @@ "node": ">= 0.8" } }, - "node_modules/memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "license": "MIT" - }, "node_modules/merge-descriptors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", @@ -3264,105 +3511,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mongodb": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.18.0.tgz", - "integrity": "sha512-fO5ttN9VC8P0F5fqtQmclAkgXZxbIkYRTUi1j8JO6IYwvamkhtYDilJr35jOPELR49zqCJgXZWwCtW7B+TM8vQ==", - "license": "Apache-2.0", - "dependencies": { - "@mongodb-js/saslprep": "^1.1.9", - "bson": "^6.10.4", - "mongodb-connection-string-url": "^3.0.0" - }, - "engines": { - "node": ">=16.20.1" - }, - "peerDependencies": { - "@aws-sdk/credential-providers": "^3.188.0", - "@mongodb-js/zstd": "^1.1.0 || ^2.0.0", - "gcp-metadata": "^5.2.0", - "kerberos": "^2.0.1", - "mongodb-client-encryption": ">=6.0.0 <7", - "snappy": "^7.2.2", - "socks": "^2.7.1" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "@mongodb-js/zstd": { - "optional": true - }, - "gcp-metadata": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "snappy": { - "optional": true - }, - "socks": { - "optional": true - } - } - }, - "node_modules/mongodb-connection-string-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", - "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", - "license": "Apache-2.0", - "dependencies": { - "@types/whatwg-url": "^11.0.2", - "whatwg-url": "^14.1.0 || ^13.0.0" - } - }, - "node_modules/mongoose": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.18.2.tgz", - "integrity": "sha512-gA6GFlshOHUdNyw9OQTmMLSGzVOPbcbjaSZ1dvR5iMp668N2UUznTuzgTY6V6Q41VtBc4kmL/qqML1RNgXB5Fg==", - "license": "MIT", - "dependencies": { - "bson": "^6.10.4", - "kareem": "2.6.3", - "mongodb": "~6.18.0", - "mpath": "0.9.0", - "mquery": "5.0.0", - "ms": "2.1.3", - "sift": "17.1.3" - }, - "engines": { - "node": ">=16.20.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mongoose" - } - }, - "node_modules/mpath": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", - "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mquery": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", - "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", - "license": "MIT", - "dependencies": { - "debug": "4.x" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -3398,6 +3546,13 @@ "node": ">= 0.6" } }, + "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/nodemon": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz", @@ -3559,6 +3714,26 @@ "node": ">=8" } }, + "node_modules/nypm": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.2.tgz", + "integrity": "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.2", + "pathe": "^2.0.3", + "pkg-types": "^2.3.0", + "tinyexec": "^1.0.1" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -3571,6 +3746,13 @@ "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", @@ -3726,12 +3908,26 @@ "url": "https://opencollective.com/express" } }, + "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/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "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/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -3767,6 +3963,18 @@ "@napi-rs/nice": "^1.0.1" } }, + "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/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3793,6 +4001,32 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/prisma": { + "version": "6.16.2", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.16.2.tgz", + "integrity": "sha512-aRvldGE5UUJTtVmFiH3WfNFNiqFlAtePUxcI0UEGlnXCX7DqhiMT5TRYwncHFeA/Reca5W6ToXXyCMTeFPdSXA==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/config": "6.16.2", + "@prisma/engines": "6.16.2" + }, + "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", @@ -3817,11 +4051,29 @@ "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/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", @@ -3889,13 +4141,23 @@ "url": "https://opencollective.com/express" } }, + "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/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", - "optional": true, - "peer": true, "engines": { "node": ">= 14.18.0" }, @@ -4227,12 +4489,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/sift": { - "version": "17.1.3", - "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", - "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==", - "license": "MIT" - }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -4324,15 +4580,6 @@ "node": ">= 12" } }, - "node_modules/sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", - "license": "MIT", - "dependencies": { - "memory-pager": "^1.0.2" - } - }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -4531,6 +4778,13 @@ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "license": "MIT" }, + "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/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -4626,18 +4880,6 @@ "nodetouch": "bin/nodetouch.js" } }, - "node_modules/tr46": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", - "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", - "license": "MIT", - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4729,28 +4971,6 @@ "node": ">= 0.8" } }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-url": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", - "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", - "license": "MIT", - "dependencies": { - "tr46": "^5.1.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 163fccf..f71af2d 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,20 @@ { "name": "codeit-backend-server", - "version": "1.0.0", + "version": "1.0.1", "description": "panda-express-server", "main": "src/server.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", "dev": "nodemon --env-file=./env/.env.development src/server.js", "start": "node dist/src/server.js", "build": "npx swc src -d dist && node dist/src/swagger.js", "format": "prettier --cache --write src/**/*.js", "lint": "eslint --cache .", - "seed": "node --env-file=./env/.env.development src/seed/seed.js" + "seed": "node --env-file=./env/.env.development scripts/seed.js", + "prisma": "dotenv -e ./env/.env.development -- prisma", + "db:push": "npm run prisma -- db push", + "migreate:dev": "npm run prisma -- migrate dev", + "migreate:reset": "npm run prisma -- migrate reset", + "studio": "npm run prisma -- studio" }, "lint-staged": { "**/*.ts": [ @@ -35,22 +39,25 @@ }, "homepage": "https://github.com/rklpoi5678/9-sprint-mission-be#readme", "dependencies": { + "@prisma/client": "^6.16.2", + "@swc/cli": "^0.7.8", + "@swc/core": "^1.13.5", + "dotenv": "^17.2.2", "express": "^5.1.0", - "mongoose": "^8.18.2", "swagger-autogen": "^2.23.7", "swagger-ui-express": "^5.0.1", - "zod": "^4.1.11", - "@swc/cli": "^0.7.8", - "@swc/core": "^1.13.5" + "zod": "^4.1.11" }, "devDependencies": { "@eslint/js": "^9.36.0", + "@faker-js/faker": "^10.0.0", "@types/express": "^5.0.3", "@types/node": "^24.5.2", "eslint": "^9.36.0", "husky": "^9.1.7", "lint-staged": "^16.2.0", "nodemon": "^3.1.10", - "prettier": "^3.6.2" + "prettier": "^3.6.2", + "prisma": "^6.16.2" } -} \ No newline at end of file +} diff --git a/prisma/migrations/20250929130145_create_user_user_profile_article_comment_tables/migration.sql b/prisma/migrations/20250929130145_create_user_user_profile_article_comment_tables/migration.sql new file mode 100644 index 0000000..00279fa --- /dev/null +++ b/prisma/migrations/20250929130145_create_user_user_profile_article_comment_tables/migration.sql @@ -0,0 +1,64 @@ +-- CreateTable +CREATE TABLE "public"."User" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "email" TEXT NOT NULL, + "password" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "deletedAt" TIMESTAMP(3), + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."UserProfile" ( + "id" SERIAL NOT NULL, + "userId" INTEGER NOT NULL, + "photoUrl" TEXT, + "bio" TEXT, + + CONSTRAINT "UserProfile_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Article" ( + "id" SERIAL NOT NULL, + "authorId" INTEGER, + "title" TEXT NOT NULL, + "content" TEXT NOT NULL, + "images" TEXT[], + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "deleteAt" TIMESTAMP(3), + + CONSTRAINT "Article_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Comment" ( + "id" SERIAL NOT NULL, + "authorId" INTEGER NOT NULL, + "articleId" INTEGER NOT NULL, + "context" TEXT NOT NULL, + + CONSTRAINT "Comment_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "public"."User"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "UserProfile_userId_key" ON "public"."UserProfile"("userId"); + +-- AddForeignKey +ALTER TABLE "public"."UserProfile" ADD CONSTRAINT "UserProfile_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Article" ADD CONSTRAINT "Article_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "public"."User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "public"."User"("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/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000..044d57c --- /dev/null +++ b/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/prisma/schema.prisma b/prisma/schema.prisma new file mode 100644 index 0000000..42eb691 --- /dev/null +++ b/prisma/schema.prisma @@ -0,0 +1,54 @@ +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "postgresql" + url = env("POSTGRESQL_URI") +} + +model User { + id Int @id @default(autoincrement()) + name String + email String @unique + password String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime? + + userProfile UserProfile? + articles Article[] + comments Comment[] +} + +model UserProfile { + id Int @id @default(autoincrement()) + userId Int @unique + photoUrl String? + bio String? + user User @relation(fields: [userId], references: [id], onDelete: Cascade) +} + +model Article { + id Int @id @default(autoincrement()) + authorId Int? + title String + content String + images String[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deleteAt DateTime? + author User? @relation(fields: [authorId], references: [id]) + + Comment Comment[] +} + +model Comment { + id Int @id @default(autoincrement()) + authorId Int + articleId Int + context String + + author User @relation(fields: [authorId], references: [id], onDelete: Cascade) + article Article @relation(fields: [articleId], references: [id], onDelete: Cascade) +} diff --git a/scripts/seed.js b/scripts/seed.js new file mode 100644 index 0000000..8a6dd24 --- /dev/null +++ b/scripts/seed.js @@ -0,0 +1,80 @@ +import { PrismaClient } from "@prisma/client"; +import { faker } from "@faker-js/faker/locale/ko"; + +const prisma = new PrismaClient(); + +async function main() { + const NUM_USERS_TO_CREATE = 5; + console.log("시딩 시작"); + + const userPromise = Array.from({ length: NUM_USERS_TO_CREATE }).map(() => + prisma.user.create({ + data: { + name: faker.person.fullName(), + email: faker.internet.email(), + password: faker.internet.password(), + userProfile: { + create: { + photoUrl: faker.image.avatar(), + bio: faker.person.bio(), + }, + }, + }, + }), + ); + + const users = await Promise.all(userPromise); + + const allPosts = []; + for (const user of users) { + const postCount = faker.number.int({ min: 1, max: 5 }); + const postPromises = Array.from({ length: NUM_USERS_TO_CREATE }).map(() => { + const randomUser = + users[faker.number.int({ min: 0, max: users.length - 1 })]; + return prisma.article.create({ + data: { + title: faker.lorem.sentence({ min: 3, max: 14 }), + content: faker.lorem.paragraph({ min: 2, max: 7 }), + images: [ + faker.image.urlPicsumPhotos({ width: 100, height: 100 }), + faker.image.urlPicsumPhotos({ width: 100, height: 100 }), + faker.image.urlPicsumPhotos({ width: 100, height: 100 }), + ], + authorId: randomUser.id, + }, + }); + }); + + const userPosts = await Promise.all(postPromises); + allPosts.push(...userPosts); + } + console.log(`${allPosts.length}개의 게시물이 생성되었습니다.`); + + for (const post of allPosts) { + const commentCount = faker.number.int({ min: 1, max: 10 }); + const commentPromises = Array.from({ length: commentCount }).map(() => { + const randomUser = + users[faker.number.int({ min: 0, max: users.length - 1 })]; + return prisma.comment.create({ + data: { + context: faker.lorem.sentences({ min: 1, max: 3 }), + authorId: randomUser.id, + articleId: post.id, + }, + }); + }); + + await Promise.all(commentPromises); + } + + console.log(`${users.length}명의 유저가 생성되었습니다.`); + console.log("데이터 시딩 완료"); +} +main() + .catch((e) => { + console.error("Seeding Error", e); + process.exit(1); + }) + .finally(async () => { + await prisma.$disconnect(); + }); diff --git a/src/config/config.js b/src/config/config.js index 350a0cf..2fa5505 100644 --- a/src/config/config.js +++ b/src/config/config.js @@ -3,7 +3,7 @@ import { z } from "zod"; const envSchema = z.object({ NODE_ENV: z.enum(["development", "production", "test"]), PORT: z.coerce.number().min(1000).max(65535), - MONGO_URI: z.string().startsWith("mongodb+srv://"), + POSTGRESQL_URI: z.string().startsWith("postgresql://"), }); const parseEnviroment = () => { @@ -11,7 +11,7 @@ const parseEnviroment = () => { return envSchema.parse({ NODE_ENV: process.env.NODE_ENV, PORT: process.env.PORT, - MONGO_URI: process.env.MONGO_URI, + POSTGRESQL_URI: process.env.POSTGRESQL_URI, }); } catch (error) { if (error instanceof z.ZodError) { diff --git a/src/seed/seed.js b/src/seed/seed.js deleted file mode 100644 index d31b518..0000000 --- a/src/seed/seed.js +++ /dev/null @@ -1,61 +0,0 @@ -import mongoose from "mongoose"; -import { Product } from "../models/product.model.js"; -import { config } from "../config/config.js"; - -const seedProducts = [ - { - name: "무선 이어폰", - description: - "선명한 사운드와 긴 배터리 수명을 자랑하는 최신 무선 이어폰입니다.", - price: 129000, - tags: "전자기기, 오디오, 무선", - }, - { - name: "스마트 워치", - description: - "건강 관리와 스마트 알림 기능을 갖춘 세련된 디자인의 스마트 워치입니다.", - price: 250000, - tags: "전자기기, 웨어러블, 스마트", - }, - { - name: "프리미엄 커피 원두", - description: "깊고 풍부한 향을 느낄 수 있는 고품질 아라비카 원두입니다.", - price: 18000, - tags: "식품, 음료, 커피", - }, - { - name: "유기농 핸드크림", - description: - "천연 재료로 만들어 피부를 촉촉하고 부드럽게 가꿔주는 핸드크림입니다.", - price: 15000, - tags: "뷰티, 화장품, 유기농", - }, - { - name: "스웨이드 재킷", - description: "부드러운 스웨이드 소재로 제작된 스타일리시한 재킷입니다.", - price: 89000, - tags: "의류, 패션, 재킷", - }, -]; - -async function seedDatabase() { - try { - await mongoose.connect(config.MONGO_URI); - console.log("MongoDB에 연결되었습니다."); - - // 기존 데이터 삭제 (선택 사항) - await Product.deleteMany({}); - console.log("기존 Product 데이터가 삭제되었습니다."); - - // 시드 데이터 삽입 - await Product.insertMany(seedProducts); - console.log("시드 데이터가 성공적으로 추가되었습니다!"); - } catch (error) { - console.error("데이터 시딩 중 오류 발생:", error); - } finally { - await mongoose.disconnect(); - console.log("MongoDB 연결이 종료되었습니다."); - } -} - -seedDatabase(); From b6d90cb94315b4137de596d44948a269355d69e7 Mon Sep 17 00:00:00 2001 From: rklpoi5678 Date: Mon, 29 Sep 2025 23:48:50 +0900 Subject: [PATCH 02/13] =?UTF-8?q?Refactor:=20=EB=A7=88=EC=9D=B4=EA=B7=B8?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98-=ED=8C=8C=EC=9D=BC=EC=9C=84?= =?UTF-8?q?=EC=B9=98=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20=EB=9D=BC=EC=9A=B0?= =?UTF-8?q?=ED=84=B0=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - common/dto,exceptions 으로 공통으로 사용되는 로직 분기 - controllers와 routes 에 v1폴더생성후 컨트롤과 라우터 각각 분리 - common/exceptions 에 index.js로 에러핸들러 한번에 내보내기 --- src/{schemas => common/dto}/Items.js | 0 .../exceptions}/badRequestException.js | 0 .../exceptions}/conflictException.js | 0 .../exceptions}/forbiddenException.js | 0 .../exceptions}/httpException.js | 0 src/common/exceptions/index.js | 5 + .../exceptions}/notFoundException.js | 0 src/controllers/v1/item.controller.js | 138 +++++++++++++++++ src/db/index.js | 26 +++- src/routes/index.js | 4 +- src/routes/items.js | 141 ------------------ src/routes/v1/items.js | 24 +++ 12 files changed, 188 insertions(+), 150 deletions(-) rename src/{schemas => common/dto}/Items.js (100%) rename src/{errors => common/exceptions}/badRequestException.js (100%) rename src/{errors => common/exceptions}/conflictException.js (100%) rename src/{errors => common/exceptions}/forbiddenException.js (100%) rename src/{errors => common/exceptions}/httpException.js (100%) create mode 100644 src/common/exceptions/index.js rename src/{errors => common/exceptions}/notFoundException.js (100%) create mode 100644 src/controllers/v1/item.controller.js delete mode 100644 src/routes/items.js create mode 100644 src/routes/v1/items.js diff --git a/src/schemas/Items.js b/src/common/dto/Items.js similarity index 100% rename from src/schemas/Items.js rename to src/common/dto/Items.js diff --git a/src/errors/badRequestException.js b/src/common/exceptions/badRequestException.js similarity index 100% rename from src/errors/badRequestException.js rename to src/common/exceptions/badRequestException.js diff --git a/src/errors/conflictException.js b/src/common/exceptions/conflictException.js similarity index 100% rename from src/errors/conflictException.js rename to src/common/exceptions/conflictException.js diff --git a/src/errors/forbiddenException.js b/src/common/exceptions/forbiddenException.js similarity index 100% rename from src/errors/forbiddenException.js rename to src/common/exceptions/forbiddenException.js diff --git a/src/errors/httpException.js b/src/common/exceptions/httpException.js similarity index 100% rename from src/errors/httpException.js rename to src/common/exceptions/httpException.js diff --git a/src/common/exceptions/index.js b/src/common/exceptions/index.js new file mode 100644 index 0000000..7fce20d --- /dev/null +++ b/src/common/exceptions/index.js @@ -0,0 +1,5 @@ +export * from "./badRequestException"; +export * from "./conflictException"; +export * from "./forbiddenException"; +export * from "./httpException"; +export * from "./notFoundException"; diff --git a/src/errors/notFoundException.js b/src/common/exceptions/notFoundException.js similarity index 100% rename from src/errors/notFoundException.js rename to src/common/exceptions/notFoundException.js diff --git a/src/controllers/v1/item.controller.js b/src/controllers/v1/item.controller.js new file mode 100644 index 0000000..4f80ea5 --- /dev/null +++ b/src/controllers/v1/item.controller.js @@ -0,0 +1,138 @@ +import { Product } from "../../models/product.model.js"; +import { NotFoundException } from "../../common/exceptions/notFoundException.js"; + +// "get AllItems" +export const getItems = async (req, res, next) => { + try { + const { + page = 1, + limit = 10, + keyword = "", + orderBy = "recent", + } = req.query; + const total = await Product.countDocuments(); + const totalPage = Math.ceil(total / limit); + + let sortOptions = {}; + if (orderBy === "recent") { + sortOptions = { createAt: -1 }; + } + if (orderBy === "oldest") { + sortOptions = { createAt: 1 }; + } + + const product = await Product.find({ + /** @see https://www.mongodb.com/docs/manual/reference/operator/query/regex/ */ + $or: [ + { name: { $regex: keyword, $options: "i" } }, + { description: { $regex: keyword, $options: "i" } }, + ], + }) + .sort(sortOptions) + .skip(limit * (page - 1)) + .limit(limit); + + res.json({ + success: true, + message: "sucess get products", + data: product, + pagination: { + page, + limit, + total, + totalPage, + }, + }); + } catch (error) { + next(error); + return; + } +}; + +// getItemsById +export const getItemById = async (req, res, next) => { + try { + const { itemId } = req.params; + const { item } = await Product.findById(itemId); + if (!item) { + throw new NotFoundException("not found item"); + } + res.json({ + sucess: true, + message: "fined items", + data: item, + }); + } catch (error) { + next(error); + return; + } +}; + +// createItemsHander +export const createItem = async (req, res, next) => { + try { + const { name, description, price, tags } = req.body; + + const newItem = await Product({ name, description, price, tags }); + await newItem.save(); + res.status(201).json({ + success: true, + message: "success create Item", + data: newItem, + }); + } catch (error) { + next(error); + return; + } +}; + +//deleteItemHandler +export const deleteItem = async (req, res, next) => { + try { + const { itemId } = req.params; + const deleteItem = await Product.findByIdAndDelete(itemId); + + if (!deleteItem) { + throw new NotFoundException("not found item"); + } + res.josn({ + success: true, + message: "success delete item", + }); + } catch (error) { + next(error); + return; + } +}; + +//patchItemHandler +export const patchItem = async (req, res, next) => { + try { + const { itemId } = req.params; + const { name, description, price, tags } = req.body; + + const updateItem = await Product.findByIdAndUpdate( + itemId, + { + name, + description, + price, + tags, + }, + { new: true }, + ); + + if (!updateItem) { + throw new NotFoundException("failed update item"); + } + + res.json({ + success: true, + message: "success update item", + data: updateItem, + }); + } catch (error) { + next(error); + return; + } +}; diff --git a/src/db/index.js b/src/db/index.js index 86aa356..29f45e5 100644 --- a/src/db/index.js +++ b/src/db/index.js @@ -1,16 +1,28 @@ -import mongoose from "mongoose"; -import { config } from "../config/config.js"; +import { PrismaClient } from "@prisma/client"; +import { exit } from "node:process"; + +const getPrismaLogLevel = () => { + if (process.env.NODE_ENV === "production") { + return ["warn", "error"]; + } + return ["query", "info", "warn", "error"]; +}; + +export const prisma = new PrismaClient({ + log: getPrismaLogLevel(), +}); export const connectDB = async () => { try { - await mongoose.connect(config.MONGO_URI); - console.log("MongoDB conneted successfully"); + await prisma.$connect(); + console.log("프리스마가 성공적으로 연결되었습니다."); } catch (error) { - console.error("MongoDB connection error:", error); - process.exit(1); + console.error(" 프리스마 를 연결하지 못했습니다.", error); + exit(1); } }; export const disconnectDB = async () => { - await mongoose.connection.close(); + await prisma.$disconnect(); + console.log("Prisma Disconnected"); }; diff --git a/src/routes/index.js b/src/routes/index.js index 095ff96..604d38a 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -1,5 +1,5 @@ import express from "express"; -import { itemRouter } from "./items.js"; +import { itemRouter } from "./v1/items.js"; export const router = express.Router(); @@ -10,4 +10,4 @@ router.get("/", (req, res) => { }); }); -router.use("/api/items", itemRouter); +router.use("/api/v1/items", itemRouter); diff --git a/src/routes/items.js b/src/routes/items.js deleted file mode 100644 index 07ae77f..0000000 --- a/src/routes/items.js +++ /dev/null @@ -1,141 +0,0 @@ -import express from "express"; -import { Product } from "../models/product.model.js"; -import { validateProduct } from "../middlewares/validateProduct.js"; -import { validateQuery } from "../middlewares/validate.js"; -import { NotFoundException } from "../errors/notFoundException.js"; -import { getItemsSchema } from "../schemas/Items.js"; - -export const itemRouter = express.Router(); - -itemRouter.get("/", validateQuery(getItemsSchema), async (req, res, next) => { - try { - const { - page = 1, - limit = 10, - keyword = "", - orderBy = "recent", - } = req.query; - const total = await Product.countDocuments(); - const totalPage = Math.ceil(total / limit); - - let sortOptions = {}; - if (orderBy === "recent") { - sortOptions = { createAt: -1 }; - } - if (orderBy === "oldest") { - sortOptions = { createAt: 1 }; - } - - const product = await Product.find({ - /** @see https://www.mongodb.com/docs/manual/reference/operator/query/regex/ */ - $or: [ - { name: { $regex: keyword, $options: "i" } }, - { description: { $regex: keyword, $options: "i" } }, - ], - }) - .sort(sortOptions) - .skip(limit * (page - 1)) - .limit(limit); - - res.json({ - success: true, - message: "sucess get products", - data: product, - pagination: { - page, - limit, - total, - totalPage, - }, - }); - } catch (error) { - next(error); - return; - } -}); - -itemRouter.get("/:productId", async (req, res, next) => { - try { - const productId = req.params.productId; - const product = await Product.findById(productId); - if (!product) { - throw new NotFoundException("not found product"); - } - res.json({ - success: true, - message: `find product`, - data: product, - }); - } catch (error) { - next(error); - return; - } -}); - -itemRouter.post("/", validateProduct, async (req, res, next) => { - try { - const { name, description, price, tags } = req.body; - - // 중고마켓 특성상 중복된 상품 - // const existingProduct = await Product.findOne({}) - const newProduct = new Product({ name, description, price, tags }); - await newProduct.save(); - res.status(201).json({ - success: true, - message: "success create product", - data: newProduct, - }); - } catch (error) { - next(error); - return; - } -}); - -itemRouter.delete("/:productId", async (req, res, next) => { - try { - const productId = req.params.productId; - const deleteProduct = await Product.findByIdAndDelete(productId); - - if (!deleteProduct) { - throw new NotFoundException("not found product"); - } - res.json({ - success: true, - message: "success create product", - }); - } catch (error) { - next(error); - return; - } -}); - -itemRouter.patch("/:productId", validateProduct, async (req, res, next) => { - try { - const { productId } = req.params.productId; - const { name, description, price, tags } = req.body; - - const updateProduct = await Product.findByIdAndUpdate( - productId, - { - name, - description, - price, - tags, - }, - { new: true } - ); - - if (!updateProduct) { - throw new NotFoundException("failed update product"); - } - - res.json({ - success: true, - message: "success update product", - data: updateProduct, - }); - } catch (error) { - next(error); - return; - } -}); diff --git a/src/routes/v1/items.js b/src/routes/v1/items.js new file mode 100644 index 0000000..3b2c83c --- /dev/null +++ b/src/routes/v1/items.js @@ -0,0 +1,24 @@ +import express from "express"; +import { validateProduct } from "../../middlewares/validateProduct.js"; +import { validateQuery } from "../../middlewares/validate.js"; +import { NotFoundException } from "../../common/exceptions/index.js"; +import { getItemsSchema } from "../common/dto/Items.js"; +import { + createItem, + deleteItem, + getItemById, + getItems, + patchItem, +} from "../../controllers/v1/item.controller.js"; + +export const itemRouter = express.Router(); + +itemRouter.get("/", validateQuery(getItemsSchema), getItems); + +itemRouter.get("/:productId", getItemById); + +itemRouter.post("/", validateProduct, createItem); + +itemRouter.delete("/:productId", deleteItem); + +itemRouter.patch("/:productId", validateProduct, patchItem); From 0ee809a361766dccaa61e5bdf48ddd63d9255cfa Mon Sep 17 00:00:00 2001 From: rklpoi5678 Date: Tue, 30 Sep 2025 00:19:22 +0900 Subject: [PATCH 03/13] =?UTF-8?q?Rename:=20prisma/schema=EB=A1=9C=20?= =?UTF-8?q?=EC=8A=A4=ED=82=A4=EB=A7=88=20=ED=8C=8C=EC=9D=BC=EB=82=98?= =?UTF-8?q?=EB=88=84=EA=B8=B0=20=EA=B8=B0=EC=A1=B4items=EB=AA=A8=EB=8D=B8?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 6 +++--- prisma/schema/board.prisma | 23 +++++++++++++++++++++++ prisma/schema/item.prisma | 10 ++++++++++ prisma/{ => schema}/schema.prisma | 24 ------------------------ schema.config.js | 5 +++++ 5 files changed, 41 insertions(+), 27 deletions(-) create mode 100644 prisma/schema/board.prisma create mode 100644 prisma/schema/item.prisma rename prisma/{ => schema}/schema.prisma (51%) create mode 100644 schema.config.js diff --git a/package.json b/package.json index f71af2d..4984799 100644 --- a/package.json +++ b/package.json @@ -11,10 +11,10 @@ "lint": "eslint --cache .", "seed": "node --env-file=./env/.env.development scripts/seed.js", "prisma": "dotenv -e ./env/.env.development -- prisma", - "db:push": "npm run prisma -- db push", - "migreate:dev": "npm run prisma -- migrate dev", + "db:push": "npm run prisma -- db push --schema ./prisma/schema", + "migreate:dev": "npm run prisma -- migrate dev --schema ./prisma/schema", "migreate:reset": "npm run prisma -- migrate reset", - "studio": "npm run prisma -- studio" + "studio": "npm run prisma -- studio --schema ./prisma/schema" }, "lint-staged": { "**/*.ts": [ diff --git a/prisma/schema/board.prisma b/prisma/schema/board.prisma new file mode 100644 index 0000000..4dbd94c --- /dev/null +++ b/prisma/schema/board.prisma @@ -0,0 +1,23 @@ +model Article { + id Int @id @default(autoincrement()) + authorId Int? + title String + content String + images String[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deleteAt DateTime? + author User? @relation(fields: [authorId], references: [id]) + + Comment Comment[] +} + +model Comment { + id Int @id @default(autoincrement()) + authorId Int + articleId Int + context String + + author User @relation(fields: [authorId], references: [id], onDelete: Cascade) + article Article @relation(fields: [articleId], references: [id], onDelete: Cascade) +} diff --git a/prisma/schema/item.prisma b/prisma/schema/item.prisma new file mode 100644 index 0000000..9cb4ff9 --- /dev/null +++ b/prisma/schema/item.prisma @@ -0,0 +1,10 @@ +model Item { + id Int @id @default(autoincrement()) + name String + description String + price Int + tags String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime +} diff --git a/prisma/schema.prisma b/prisma/schema/schema.prisma similarity index 51% rename from prisma/schema.prisma rename to prisma/schema/schema.prisma index 42eb691..8ec1342 100644 --- a/prisma/schema.prisma +++ b/prisma/schema/schema.prisma @@ -28,27 +28,3 @@ model UserProfile { bio String? user User @relation(fields: [userId], references: [id], onDelete: Cascade) } - -model Article { - id Int @id @default(autoincrement()) - authorId Int? - title String - content String - images String[] - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deleteAt DateTime? - author User? @relation(fields: [authorId], references: [id]) - - Comment Comment[] -} - -model Comment { - id Int @id @default(autoincrement()) - authorId Int - articleId Int - context String - - author User @relation(fields: [authorId], references: [id], onDelete: Cascade) - article Article @relation(fields: [articleId], references: [id], onDelete: Cascade) -} diff --git a/schema.config.js b/schema.config.js new file mode 100644 index 0000000..803c3e2 --- /dev/null +++ b/schema.config.js @@ -0,0 +1,5 @@ +import path from "node:path"; + +export default { + schema: path.join("prisma", "schema"), +}; From 4ce7cc827e3f61a11ba6e3e11498227338f753eb Mon Sep 17 00:00:00 2001 From: rklpoi5678 Date: Tue, 30 Sep 2025 10:45:09 +0900 Subject: [PATCH 04/13] =?UTF-8?q?Refactor:=20=EB=A7=88=EC=9D=B4=EA=B7=B8?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98-=20item=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=EC=97=90=EC=84=9C=20=EA=B8=B0=EC=A1=B4=20mongoose?= =?UTF-8?q?=EC=BD=94=EB=93=9C=EB=A5=BC=20->=20prisma=EB=A1=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/pull-request-template.md | 12 --- package.json | 2 +- prisma/schema/item.prisma | 13 ++-- .../migration.sql | 78 +++++++++++++++++++ prisma/schema/migrations/migration_lock.toml | 3 + prisma/schema/schema.prisma | 1 + scripts/seed.js | 19 +++++ src/common/exceptions/index.js | 10 +-- src/controllers/v1/item.controller.js | 65 +++++++++------- src/middlewares/errorHandler.js | 2 +- src/middlewares/validateProduct.js | 6 +- src/models/product.model.js | 21 ----- src/routes/v1/items.js | 3 +- 13 files changed, 159 insertions(+), 76 deletions(-) create mode 100644 prisma/schema/migrations/20250930001747_create_item_tabel/migration.sql create mode 100644 prisma/schema/migrations/migration_lock.toml delete mode 100644 src/models/product.model.js diff --git a/.github/pull-request-template.md b/.github/pull-request-template.md index a858147..74adb5f 100644 --- a/.github/pull-request-template.md +++ b/.github/pull-request-template.md @@ -2,26 +2,14 @@ ### 기본 -- [x] -- [] -- [] - ### 심화 -- [x] -- [] - ## 주요 변경사항 -- -- - ## 스크린샷 ![image](이미지url) ## 멘토에게 - -- - - 셀프 코드 리뷰를 통해 질문 이어가겠습니다. diff --git a/package.json b/package.json index 4984799..f529aed 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "prisma": "dotenv -e ./env/.env.development -- prisma", "db:push": "npm run prisma -- db push --schema ./prisma/schema", "migreate:dev": "npm run prisma -- migrate dev --schema ./prisma/schema", - "migreate:reset": "npm run prisma -- migrate reset", + "migreate:reset": "npm run prisma -- migrate reset --schema ./prisma/schema", "studio": "npm run prisma -- studio --schema ./prisma/schema" }, "lint-staged": { diff --git a/prisma/schema/item.prisma b/prisma/schema/item.prisma index 9cb4ff9..de24bee 100644 --- a/prisma/schema/item.prisma +++ b/prisma/schema/item.prisma @@ -1,10 +1,13 @@ model Item { - id Int @id @default(autoincrement()) + id Int @id @default(autoincrement()) + userId Int? name String description String - price Int + price String tags String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deletedAt DateTime + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime? + + user User? @relation(fields: [userId], references: [id], onDelete: Cascade) } diff --git a/prisma/schema/migrations/20250930001747_create_item_tabel/migration.sql b/prisma/schema/migrations/20250930001747_create_item_tabel/migration.sql new file mode 100644 index 0000000..f0fd0a8 --- /dev/null +++ b/prisma/schema/migrations/20250930001747_create_item_tabel/migration.sql @@ -0,0 +1,78 @@ +-- CreateTable +CREATE TABLE "public"."Article" ( + "id" SERIAL NOT NULL, + "authorId" INTEGER, + "title" TEXT NOT NULL, + "content" TEXT NOT NULL, + "images" TEXT[], + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "deleteAt" TIMESTAMP(3), + + CONSTRAINT "Article_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Comment" ( + "id" SERIAL NOT NULL, + "authorId" INTEGER NOT NULL, + "articleId" INTEGER NOT NULL, + "context" TEXT NOT NULL, + + CONSTRAINT "Comment_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Item" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT NOT NULL, + "price" INTEGER NOT NULL, + "tags" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "deletedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Item_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."User" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "email" TEXT NOT NULL, + "password" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "deletedAt" TIMESTAMP(3), + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."UserProfile" ( + "id" SERIAL NOT NULL, + "userId" INTEGER NOT NULL, + "photoUrl" TEXT, + "bio" TEXT, + + CONSTRAINT "UserProfile_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "public"."User"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "UserProfile_userId_key" ON "public"."UserProfile"("userId"); + +-- AddForeignKey +ALTER TABLE "public"."Article" ADD CONSTRAINT "Article_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "public"."User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Comment" ADD CONSTRAINT "Comment_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "public"."User"("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"."UserProfile" ADD CONSTRAINT "UserProfile_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/schema/migrations/migration_lock.toml b/prisma/schema/migrations/migration_lock.toml new file mode 100644 index 0000000..044d57c --- /dev/null +++ b/prisma/schema/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/prisma/schema/schema.prisma b/prisma/schema/schema.prisma index 8ec1342..61d6cde 100644 --- a/prisma/schema/schema.prisma +++ b/prisma/schema/schema.prisma @@ -19,6 +19,7 @@ model User { userProfile UserProfile? articles Article[] comments Comment[] + items Item[] } model UserProfile { diff --git a/scripts/seed.js b/scripts/seed.js index 8a6dd24..a2bc69a 100644 --- a/scripts/seed.js +++ b/scripts/seed.js @@ -50,6 +50,25 @@ async function main() { } console.log(`${allPosts.length}개의 게시물이 생성되었습니다.`); + for (const user of users) { + const itemCount = faker.number.int({ min: 1, max: 7 }); + const itemPromises = Array.from({ length: itemCount }).map(() => { + const randomUser = + users[faker.number.int({ min: 0, max: users.length - 1 })]; + return prisma.item.create({ + data: { + userId: randomUser.id, + name: faker.commerce.product(), + description: faker.lorem.paragraph({ min: 2, max: 7 }), + price: faker.commerce.price({ min: 1000, symbol: "₩" }), + tags: faker.lorem.sentences({ min: 1, max: 3 }), + }, + }); + }); + + await Promise.all(itemPromises); + } + for (const post of allPosts) { const commentCount = faker.number.int({ min: 1, max: 10 }); const commentPromises = Array.from({ length: commentCount }).map(() => { diff --git a/src/common/exceptions/index.js b/src/common/exceptions/index.js index 7fce20d..83129cf 100644 --- a/src/common/exceptions/index.js +++ b/src/common/exceptions/index.js @@ -1,5 +1,5 @@ -export * from "./badRequestException"; -export * from "./conflictException"; -export * from "./forbiddenException"; -export * from "./httpException"; -export * from "./notFoundException"; +export * from "./badRequestException.js"; +export * from "./conflictException.js"; +export * from "./forbiddenException.js"; +export * from "./httpException.js"; +export * from "./notFoundException.js"; diff --git a/src/controllers/v1/item.controller.js b/src/controllers/v1/item.controller.js index 4f80ea5..5963f11 100644 --- a/src/controllers/v1/item.controller.js +++ b/src/controllers/v1/item.controller.js @@ -1,36 +1,39 @@ -import { Product } from "../../models/product.model.js"; +import { prisma } from "../../db/index.js"; import { NotFoundException } from "../../common/exceptions/notFoundException.js"; // "get AllItems" export const getItems = async (req, res, next) => { try { const { - page = 1, - limit = 10, + page: pageStr = 1, + limit: limitStr = 10, keyword = "", orderBy = "recent", } = req.query; - const total = await Product.countDocuments(); + const page = parseInt(pageStr); + const limit = parseInt(limitStr); + const total = await prisma.item.count(); const totalPage = Math.ceil(total / limit); let sortOptions = {}; if (orderBy === "recent") { - sortOptions = { createAt: -1 }; + sortOptions = { createdAt: "desc" }; } if (orderBy === "oldest") { - sortOptions = { createAt: 1 }; + sortOptions = { createdAt: "asc" }; } - const product = await Product.find({ - /** @see https://www.mongodb.com/docs/manual/reference/operator/query/regex/ */ - $or: [ - { name: { $regex: keyword, $options: "i" } }, - { description: { $regex: keyword, $options: "i" } }, - ], - }) - .sort(sortOptions) - .skip(limit * (page - 1)) - .limit(limit); + const product = await prisma.item.findMany({ + where: { + OR: [ + { name: { contains: keyword, mode: "insensitive" } }, + { description: { contains: keyword, mode: "insensitive" } }, + ], + }, + orderBy: sortOptions, + skip: limit * (page - 1), + take: limit, + }); res.json({ success: true, @@ -53,7 +56,10 @@ export const getItems = async (req, res, next) => { export const getItemById = async (req, res, next) => { try { const { itemId } = req.params; - const { item } = await Product.findById(itemId); + const { item } = await prisma.item.findUnique({ + where: { id: parseInt(itemId) }, + }); + if (!item) { throw new NotFoundException("not found item"); } @@ -73,8 +79,14 @@ export const createItem = async (req, res, next) => { try { const { name, description, price, tags } = req.body; - const newItem = await Product({ name, description, price, tags }); - await newItem.save(); + const newItem = await prisma.item.create({ + data: { + name, + description, + price, + tags, + }, + }); res.status(201).json({ success: true, message: "success create Item", @@ -90,12 +102,14 @@ export const createItem = async (req, res, next) => { export const deleteItem = async (req, res, next) => { try { const { itemId } = req.params; - const deleteItem = await Product.findByIdAndDelete(itemId); + const deleteItem = await prisma.item.findUnique({ + where: { id: parseInt(itemId) }, + }); if (!deleteItem) { throw new NotFoundException("not found item"); } - res.josn({ + res.json({ success: true, message: "success delete item", }); @@ -111,16 +125,15 @@ export const patchItem = async (req, res, next) => { const { itemId } = req.params; const { name, description, price, tags } = req.body; - const updateItem = await Product.findByIdAndUpdate( - itemId, - { + const updateItem = await prisma.item.update({ + where: { id: parseInt(itemId) }, + data: { name, description, price, tags, }, - { new: true }, - ); + }); if (!updateItem) { throw new NotFoundException("failed update item"); diff --git a/src/middlewares/errorHandler.js b/src/middlewares/errorHandler.js index 6194107..40d6a8c 100644 --- a/src/middlewares/errorHandler.js +++ b/src/middlewares/errorHandler.js @@ -1,5 +1,5 @@ import { isDevelopment } from "../config/config.js"; -import { HttpException } from "../errors/httpException.js"; +import { HttpException } from "../common/exceptions/index.js"; export const errorHandler = (error, req, res, next) => { console.error("error", error); diff --git a/src/middlewares/validateProduct.js b/src/middlewares/validateProduct.js index 8a80f1d..207fe71 100644 --- a/src/middlewares/validateProduct.js +++ b/src/middlewares/validateProduct.js @@ -1,4 +1,4 @@ -import { BadRequestException } from "../errors/badRequestException.js"; +import { BadRequestException } from "../common/exceptions/index.js"; const NAME_MIN_LEN = 1; const NAME_MAX_LEN = 10; @@ -15,7 +15,7 @@ export const validateProduct = (req, res, next) => { name.trim().length < NAME_MIN_LEN ) { throw new BadRequestException( - "상품이름은 1글자 이상 10자 이내여야 합니다" + "상품이름은 1글자 이상 10자 이내여야 합니다", ); } @@ -25,7 +25,7 @@ export const validateProduct = (req, res, next) => { description.trim().length < DISCRIBE_MIN_LEN ) { throw new BadRequestException( - "상품이름은 2글자 에서 100글자 사이여야 합니다" + "상품이름은 2글자 에서 100글자 사이여야 합니다", ); } diff --git a/src/models/product.model.js b/src/models/product.model.js deleted file mode 100644 index 4eee696..0000000 --- a/src/models/product.model.js +++ /dev/null @@ -1,21 +0,0 @@ -import mongoose from "mongoose"; - -const productSchema = new mongoose.Schema( - { - name: { type: String, require: true }, - description: { type: String, require: true }, - price: { type: Number, require: true }, - tags: { type: String }, - }, - { - timestamps: { - createdAt: "created_at", - updatedAt: "updated_at", - }, - }, -); - -// name, description에 포함된 단어로 검색 -> 복합 인덱스 -productSchema.index({ name: "text", description: "text" }); - -export const Product = mongoose.model("Product", productSchema, "products"); diff --git a/src/routes/v1/items.js b/src/routes/v1/items.js index 3b2c83c..aca6a61 100644 --- a/src/routes/v1/items.js +++ b/src/routes/v1/items.js @@ -1,8 +1,7 @@ import express from "express"; import { validateProduct } from "../../middlewares/validateProduct.js"; import { validateQuery } from "../../middlewares/validate.js"; -import { NotFoundException } from "../../common/exceptions/index.js"; -import { getItemsSchema } from "../common/dto/Items.js"; +import { getItemsSchema } from "../../common/dto/Items.js"; import { createItem, deleteItem, From ac3625ddff7ae7237987846107ab3ea342e4f073 Mon Sep 17 00:00:00 2001 From: rklpoi5678 Date: Tue, 30 Sep 2025 15:18:26 +0900 Subject: [PATCH 05/13] =?UTF-8?q?Feat:=20articles=EB=9D=BC=EC=9A=B0?= =?UTF-8?q?=ED=84=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/index.js | 2 + src/routes/v1/articles.js | 157 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 src/routes/v1/articles.js diff --git a/src/routes/index.js b/src/routes/index.js index 604d38a..d75ad79 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -1,5 +1,6 @@ import express from "express"; import { itemRouter } from "./v1/items.js"; +import { articleRouter } from "./v1/articles.js"; export const router = express.Router(); @@ -11,3 +12,4 @@ router.get("/", (req, res) => { }); router.use("/api/v1/items", itemRouter); +router.use("/api/v1/articles", articleRouter); diff --git a/src/routes/v1/articles.js b/src/routes/v1/articles.js new file mode 100644 index 0000000..0cf1e16 --- /dev/null +++ b/src/routes/v1/articles.js @@ -0,0 +1,157 @@ +import express from "express"; +import { prisma } from "../../db/index.js"; +import { NotFoundException } from "../../common/exceptions/index.js"; + +export const articleRouter = express.Router(); + +articleRouter.get("/", async (req, res, next) => { + try { + const { + page: pageStr = 1, + limit: limitStr = 10, + keyword = "", + orderBy = "recent", + } = req.query; + + const page = parseInt(pageStr); + const limit = parseInt(limitStr); + const total = await prisma.article.count(); + const totalPage = Math.ceil(total / limit); + + let sortOptions = {}; + if (orderBy === "recent") { + sortOptions = { createdAt: "desc" }; + } + if (orderBy === "oldest") { + sortOptions = { createdAt: "asc" }; + } + + const article = await prisma.article.findMany({ + where: { + OR: [ + { title: { contains: keyword, mode: "insensitive" } }, + { content: { contains: keyword, mode: "insensitive" } }, + ], + }, + orderBy: sortOptions, + skip: limit * (page - 1), + take: limit, + }); + + res.status(200).json({ + success: true, + message: "success get articls", + data: article, + pagination: { + page, + limit, + total, + totalPage, + }, + }); + } catch (error) { + next(error); + return; + } +}); + +articleRouter.get("/:articleId", async (req, res, next) => { + try { + const { articleId } = req.params; + const article = await prisma.article.findUnique({ + where: { id: parseInt(articleId) }, + }); + + if (!article) { + throw new NotFoundException("해당게시물을 찾을수없습니다."); + } + + res.status(200).json({ + success: true, + message: "success get article", + data: article, + }); + } catch (error) { + next(error); + return; + } +}); + +articleRouter.post("/", async (req, res, next) => { + try { + const { title, content, images } = req.body; + + // TODO: userId + const newArticle = await prisma.article.create({ + data: { + title, + content, + images, + }, + }); + + res.status(201).json({ + success: true, + message: "success create article", + data: newArticle, + }); + } catch (error) { + next(error); + return; + } +}); + +articleRouter.patch("/:articleId", async (req, res, next) => { + try { + const { articleId } = req.params; + const { title, content, images } = req.body; + + const updateArticle = await prisma.article.update({ + where: { id: parseInt(articleId) }, + data: { + title, + content, + images, + }, + }); + + if (!updateArticle) { + throw new NotFoundException("수정에 실패하였습니다."); + } + + res.status(200).json({ + success: true, + message: "success update article", + data: updateArticle, + }); + } catch (error) { + next(error); + return; + } +}); + +articleRouter.delete("/:articleId", async (req, res, next) => { + try { + const { articleId } = req.params; + const deleteArticle = await prisma.article.delete({ + where: { id: parseInt(articleId) }, + }); + + if (!deleteArticle) { + throw new NotFoundException("게시물을 찾을 수 없습니다."); + } + + res.status(200).json({ + success: true, + message: "success delete article", + data: deleteArticle, + }); + } catch (error) { + if (error.code === "P2025") { + next(new NotFoundException("Failed delete article")); + } else { + next(error); + } + return; + } +}); From a2ca493767f0326b3b9056542f1e59a3f6f5f8e4 Mon Sep 17 00:00:00 2001 From: rklpoi5678 Date: Tue, 30 Sep 2025 21:52:09 +0900 Subject: [PATCH 06/13] =?UTF-8?q?Fix:=20=EC=8A=A4=ED=82=A4=EB=A7=88?= =?UTF-8?q?=EC=97=90=20views=EC=B6=94=EA=B0=80,=20=EA=B8=B0=EC=A1=B4=20sor?= =?UTF-8?q?tOptio=20=EB=A3=A9=EC=97=85=ED=85=8C=EC=9D=B4=EB=B8=94=EB=A1=9C?= =?UTF-8?q?=20=EC=88=98=EC=A0=95n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prisma/schema/board.prisma | 1 + src/controllers/v1/item.controller.js | 13 ++++++------- src/routes/v1/articles.js | 16 +++++++++------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/prisma/schema/board.prisma b/prisma/schema/board.prisma index 4dbd94c..b5f28cc 100644 --- a/prisma/schema/board.prisma +++ b/prisma/schema/board.prisma @@ -4,6 +4,7 @@ model Article { title String content String images String[] + view Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deleteAt DateTime? diff --git a/src/controllers/v1/item.controller.js b/src/controllers/v1/item.controller.js index 5963f11..2546a24 100644 --- a/src/controllers/v1/item.controller.js +++ b/src/controllers/v1/item.controller.js @@ -15,13 +15,12 @@ export const getItems = async (req, res, next) => { const total = await prisma.item.count(); const totalPage = Math.ceil(total / limit); - let sortOptions = {}; - if (orderBy === "recent") { - sortOptions = { createdAt: "desc" }; - } - if (orderBy === "oldest") { - sortOptions = { createdAt: "asc" }; - } + const SORT_MAP = { + recent: { createdAt: "desc" }, + oldest: { createdAt: "asc" }, + }; + + const sortOptions = SORT_MAP[orderBy] ?? {}; const product = await prisma.item.findMany({ where: { diff --git a/src/routes/v1/articles.js b/src/routes/v1/articles.js index 0cf1e16..484a2d2 100644 --- a/src/routes/v1/articles.js +++ b/src/routes/v1/articles.js @@ -18,13 +18,12 @@ articleRouter.get("/", async (req, res, next) => { const total = await prisma.article.count(); const totalPage = Math.ceil(total / limit); - let sortOptions = {}; - if (orderBy === "recent") { - sortOptions = { createdAt: "desc" }; - } - if (orderBy === "oldest") { - sortOptions = { createdAt: "asc" }; - } + const SORT_MAP = { + recent: { createdAt: "desc" }, + oldest: { createdAt: "asc" }, + }; + + const sortOptions = SORT_MAP[orderBy] ?? {}; const article = await prisma.article.findMany({ where: { @@ -60,6 +59,9 @@ articleRouter.get("/:articleId", async (req, res, next) => { const { articleId } = req.params; const article = await prisma.article.findUnique({ where: { id: parseInt(articleId) }, + include: { + Comment: true, + }, }); if (!article) { From 7135e6b8c48ef01f126782c031f589b3aaa902d4 Mon Sep 17 00:00:00 2001 From: rklpoi5678 Date: Thu, 2 Oct 2025 13:32:26 +0900 Subject: [PATCH 07/13] =?UTF-8?q?Fix:=20=EC=8A=A4=ED=82=A4=EB=A7=88=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 3 +- Archive.zip | Bin 0 -> 65519 bytes package.json | 4 +- prisma/schema/board.prisma | 5 +- .../migration.sql | 21 ++++++++ src/middlewares/cors.js | 10 +++- src/routes/v1/articles.js | 50 +++++++++++++++++- 7 files changed, 86 insertions(+), 7 deletions(-) create mode 100644 Archive.zip create mode 100644 prisma/schema/migrations/20250930132727_update_comment_item/migration.sql diff --git a/.env.example b/.env.example index 7b1ac2f..2096856 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,4 @@ NODE_ENV= PORT= -POSTGRESQL_URI=mongodb+srv://:@.veiwzrz.mongodb.net/?retryWrites=true&w=majority&appName= +# MONGO_URI=mongodb+srv://:@.veiwzrz.mongodb.net/?retryWrites=true&w=majority&appName= +POSTGRESQL_URI="postgresql://:@localhost:5432/?schema=public&connection_limit=10&pool_timeout=20"; diff --git a/Archive.zip b/Archive.zip new file mode 100644 index 0000000000000000000000000000000000000000..6b7feea6d426738ef8871b33ad4a394d0146588f GIT binary patch literal 65519 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

|SCw=<3K?&#Va+e6vlO^CSH+P`(yJ&S6ma%+q8 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 Q;s<_wfQR literal 0 HcmV?d00001 diff --git a/package.json b/package.json index f529aed..f528e2c 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,8 @@ "seed": "node --env-file=./env/.env.development scripts/seed.js", "prisma": "dotenv -e ./env/.env.development -- prisma", "db:push": "npm run prisma -- db push --schema ./prisma/schema", - "migreate:dev": "npm run prisma -- migrate dev --schema ./prisma/schema", - "migreate:reset": "npm run prisma -- migrate reset --schema ./prisma/schema", + "migrate:dev": "npm run prisma -- migrate dev --schema ./prisma/schema", + "migrate:reset": "npm run prisma -- migrate reset --schema ./prisma/schema", "studio": "npm run prisma -- studio --schema ./prisma/schema" }, "lint-staged": { diff --git a/prisma/schema/board.prisma b/prisma/schema/board.prisma index b5f28cc..e366110 100644 --- a/prisma/schema/board.prisma +++ b/prisma/schema/board.prisma @@ -14,10 +14,13 @@ model Article { } model Comment { - id Int @id @default(autoincrement()) + id Int @id @default(autoincrement()) authorId Int articleId Int context String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime? author User @relation(fields: [authorId], references: [id], onDelete: Cascade) article Article @relation(fields: [articleId], references: [id], onDelete: Cascade) diff --git a/prisma/schema/migrations/20250930132727_update_comment_item/migration.sql b/prisma/schema/migrations/20250930132727_update_comment_item/migration.sql new file mode 100644 index 0000000..79ae160 --- /dev/null +++ b/prisma/schema/migrations/20250930132727_update_comment_item/migration.sql @@ -0,0 +1,21 @@ +/* + Warnings: + + - Added the required column `updatedAt` to the `Comment` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "public"."Article" ADD COLUMN "view" INTEGER NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "public"."Comment" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "deletedAt" TIMESTAMP(3), +ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL; + +-- AlterTable +ALTER TABLE "public"."Item" ADD COLUMN "userId" INTEGER, +ALTER COLUMN "price" SET DATA TYPE TEXT, +ALTER COLUMN "deletedAt" DROP NOT NULL; + +-- AddForeignKey +ALTER TABLE "public"."Item" ADD CONSTRAINT "Item_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/src/middlewares/cors.js b/src/middlewares/cors.js index 92752c7..61fc2ed 100644 --- a/src/middlewares/cors.js +++ b/src/middlewares/cors.js @@ -3,17 +3,23 @@ import { isDevelopment } from "../config/config.js"; export const cors = (req, res, next) => { const origin = req.headers.origin || req.headers.host || ""; - const whiteList = ["https://pandasmarket.netlify.app"]; + const whiteList = [ + "https://pandasmarket.netlify.app", + "http://localhost:5173", + ]; const isAllowed = isDevelopment || whiteList.includes(origin); if (isAllowed) { res.header("Access-Control-Allow-Origin", origin); } res.setHeader("Access-Control-Allow-Credentials", "true"); res.setHeader( - "Access-Control-Allow-Method", + "Access-Control-Allow-Methods", "GET,POST,PUT,PATCH,DELETE,OPTIONS", ); res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"); + if (req.method === "OPTIONS") { + return res.sendStatus(204); // No Content + } next(); }; diff --git a/src/routes/v1/articles.js b/src/routes/v1/articles.js index 484a2d2..646b0df 100644 --- a/src/routes/v1/articles.js +++ b/src/routes/v1/articles.js @@ -32,6 +32,13 @@ articleRouter.get("/", async (req, res, next) => { { content: { contains: keyword, mode: "insensitive" } }, ], }, + include: { + author: { + include: { + userProfile: true, + }, + }, + }, orderBy: sortOptions, skip: limit * (page - 1), take: limit, @@ -60,7 +67,20 @@ articleRouter.get("/:articleId", async (req, res, next) => { const article = await prisma.article.findUnique({ where: { id: parseInt(articleId) }, include: { - Comment: true, + Comment: { + include: { + author: { + include: { + userProfile: true, + }, + }, + }, + }, + author: { + include: { + userProfile: true, + }, + }, }, }); @@ -132,6 +152,34 @@ articleRouter.patch("/:articleId", async (req, res, next) => { } }); +articleRouter.patch("/:articleId/views", async (req, res, next) => { + try { + const { articleId } = req.params; + + const updateArticle = await prisma.article.update({ + where: { id: parseInt(articleId) }, + data: { + view: { + increment: 1, + }, + }, + }); + + if (!updateArticle) { + throw new NotFoundException("수정에 실패하였습니다."); + } + + res.status(200).json({ + success: true, + message: "success update article", + data: updateArticle, + }); + } catch (error) { + next(error); + return; + } +}); + articleRouter.delete("/:articleId", async (req, res, next) => { try { const { articleId } = req.params; From bfef9e4155734740eb9d2824838edde7ab980581 Mon Sep 17 00:00:00 2001 From: rklpoi5678 Date: Thu, 2 Oct 2025 16:52:59 +0900 Subject: [PATCH 08/13] =?UTF-8?q?Style:=20=ED=94=84=EB=A1=9C=EB=8D=95?= =?UTF-8?q?=EC=85=98=EC=9C=BC=EB=A1=9C=20=EC=84=A4=EC=A0=95=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .swcrc | 3 +- Archive.zip | Bin 65519 -> 0 bytes bun.lock | 836 ++++++++++++++++++++++++++++++++++++++++++++ eslint.confg.js | 22 +- package.json | 4 +- prittier..config.js | 11 + 6 files changed, 862 insertions(+), 14 deletions(-) delete mode 100644 Archive.zip create mode 100644 bun.lock create mode 100644 prittier..config.js diff --git a/.swcrc b/.swcrc index 3ab1601..7a1679c 100644 --- a/.swcrc +++ b/.swcrc @@ -13,5 +13,4 @@ "module": { "type": "commonjs" }, - "sourceMaps": true -} \ No newline at end of file +} diff --git a/Archive.zip b/Archive.zip deleted file mode 100644 index 6b7feea6d426738ef8871b33ad4a394d0146588f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65519 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

|SCw=<3K?&#Va+e6vlO^CSH+P`(yJ&S6ma%+q8 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 Q;s<_wfQR diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..00ed0e2 --- /dev/null +++ b/bun.lock @@ -0,0 +1,836 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "codeit-backend-server", + "dependencies": { + "@prisma/client": "^6.16.2", + "@swc/cli": "^0.7.8", + "@swc/core": "^1.13.5", + "dotenv": "^17.2.2", + "express": "^5.1.0", + "swagger-autogen": "^2.23.7", + "swagger-ui-express": "^5.0.1", + "zod": "^4.1.11", + }, + "devDependencies": { + "@eslint/js": "^9.36.0", + "@faker-js/faker": "^10.0.0", + "@types/express": "^5.0.3", + "@types/node": "^24.5.2", + "eslint": "^9.36.0", + "eslint-config-prettier": "^10.1.8", + "husky": "^9.1.7", + "lint-staged": "^16.2.0", + "nodemon": "^3.1.10", + "prettier": "^3.6.2", + "prisma": "^6.16.2", + }, + }, + }, + "packages": { + "@borewit/text-codec": ["@borewit/text-codec@0.1.1", "", {}, "sha512-5L/uBxmjaCIX5h8Z+uu+kA9BQLkc/Wl06UGR5ajNRxu+/XjonB5i8JpgFMrPj3LXTCPA0pv8yxUvbUi+QthGGA=="], + + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g=="], + + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], + + "@eslint/config-array": ["@eslint/config-array@0.21.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ=="], + + "@eslint/config-helpers": ["@eslint/config-helpers@0.3.1", "", {}, "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA=="], + + "@eslint/core": ["@eslint/core@0.15.2", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg=="], + + "@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "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" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="], + + "@eslint/js": ["@eslint/js@9.36.0", "", {}, "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw=="], + + "@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="], + + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.5", "", { "dependencies": { "@eslint/core": "^0.15.2", "levn": "^0.4.1" } }, "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w=="], + + "@faker-js/faker": ["@faker-js/faker@10.0.0", "", {}, "sha512-UollFEUkVXutsaP+Vndjxar40Gs5JL2HeLcl8xO1QAjJgOdhc3OmBFWyEylS+RddWaaBiAzH+5/17PLQJwDiLw=="], + + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], + + "@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="], + + "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], + + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], + + "@napi-rs/nice": ["@napi-rs/nice@1.1.1", "", { "optionalDependencies": { "@napi-rs/nice-android-arm-eabi": "1.1.1", "@napi-rs/nice-android-arm64": "1.1.1", "@napi-rs/nice-darwin-arm64": "1.1.1", "@napi-rs/nice-darwin-x64": "1.1.1", "@napi-rs/nice-freebsd-x64": "1.1.1", "@napi-rs/nice-linux-arm-gnueabihf": "1.1.1", "@napi-rs/nice-linux-arm64-gnu": "1.1.1", "@napi-rs/nice-linux-arm64-musl": "1.1.1", "@napi-rs/nice-linux-ppc64-gnu": "1.1.1", "@napi-rs/nice-linux-riscv64-gnu": "1.1.1", "@napi-rs/nice-linux-s390x-gnu": "1.1.1", "@napi-rs/nice-linux-x64-gnu": "1.1.1", "@napi-rs/nice-linux-x64-musl": "1.1.1", "@napi-rs/nice-openharmony-arm64": "1.1.1", "@napi-rs/nice-win32-arm64-msvc": "1.1.1", "@napi-rs/nice-win32-ia32-msvc": "1.1.1", "@napi-rs/nice-win32-x64-msvc": "1.1.1" } }, "sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw=="], + + "@napi-rs/nice-android-arm-eabi": ["@napi-rs/nice-android-arm-eabi@1.1.1", "", { "os": "android", "cpu": "arm" }, "sha512-kjirL3N6TnRPv5iuHw36wnucNqXAO46dzK9oPb0wj076R5Xm8PfUVA9nAFB5ZNMmfJQJVKACAPd/Z2KYMppthw=="], + + "@napi-rs/nice-android-arm64": ["@napi-rs/nice-android-arm64@1.1.1", "", { "os": "android", "cpu": "arm64" }, "sha512-blG0i7dXgbInN5urONoUCNf+DUEAavRffrO7fZSeoRMJc5qD+BJeNcpr54msPF6qfDD6kzs9AQJogZvT2KD5nw=="], + + "@napi-rs/nice-darwin-arm64": ["@napi-rs/nice-darwin-arm64@1.1.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-s/E7w45NaLqTGuOjC2p96pct4jRfo61xb9bU1unM/MJ/RFkKlJyJDx7OJI/O0ll/hrfpqKopuAFDV8yo0hfT7A=="], + + "@napi-rs/nice-darwin-x64": ["@napi-rs/nice-darwin-x64@1.1.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-dGoEBnVpsdcC+oHHmW1LRK5eiyzLwdgNQq3BmZIav+9/5WTZwBYX7r5ZkQC07Nxd3KHOCkgbHSh4wPkH1N1LiQ=="], + + "@napi-rs/nice-freebsd-x64": ["@napi-rs/nice-freebsd-x64@1.1.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kHv4kEHAylMYmlNwcQcDtXjklYp4FCf0b05E+0h6nDHsZ+F0bDe04U/tXNOqrx5CmIAth4vwfkjjUmp4c4JktQ=="], + + "@napi-rs/nice-linux-arm-gnueabihf": ["@napi-rs/nice-linux-arm-gnueabihf@1.1.1", "", { "os": "linux", "cpu": "arm" }, "sha512-E1t7K0efyKXZDoZg1LzCOLxgolxV58HCkaEkEvIYQx12ht2pa8hoBo+4OB3qh7e+QiBlp1SRf+voWUZFxyhyqg=="], + + "@napi-rs/nice-linux-arm64-gnu": ["@napi-rs/nice-linux-arm64-gnu@1.1.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-CIKLA12DTIZlmTaaKhQP88R3Xao+gyJxNWEn04wZwC2wmRapNnxCUZkVwggInMJvtVElA+D4ZzOU5sX4jV+SmQ=="], + + "@napi-rs/nice-linux-arm64-musl": ["@napi-rs/nice-linux-arm64-musl@1.1.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg=="], + + "@napi-rs/nice-linux-ppc64-gnu": ["@napi-rs/nice-linux-ppc64-gnu@1.1.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-4FS8oc0GeHpwvv4tKciKkw3Y4jKsL7FRhaOeiPei0X9T4Jd619wHNe4xCLmN2EMgZoeGg+Q7GY7BsvwKpL22Tg=="], + + "@napi-rs/nice-linux-riscv64-gnu": ["@napi-rs/nice-linux-riscv64-gnu@1.1.1", "", { "os": "linux", "cpu": "none" }, "sha512-HU0nw9uD4FO/oGCCk409tCi5IzIZpH2agE6nN4fqpwVlCn5BOq0MS1dXGjXaG17JaAvrlpV5ZeyZwSon10XOXw=="], + + "@napi-rs/nice-linux-s390x-gnu": ["@napi-rs/nice-linux-s390x-gnu@1.1.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-2YqKJWWl24EwrX0DzCQgPLKQBxYDdBxOHot1KWEq7aY2uYeX+Uvtv4I8xFVVygJDgf6/92h9N3Y43WPx8+PAgQ=="], + + "@napi-rs/nice-linux-x64-gnu": ["@napi-rs/nice-linux-x64-gnu@1.1.1", "", { "os": "linux", "cpu": "x64" }, "sha512-/gaNz3R92t+dcrfCw/96pDopcmec7oCcAQ3l/M+Zxr82KT4DljD37CpgrnXV+pJC263JkW572pdbP3hP+KjcIg=="], + + "@napi-rs/nice-linux-x64-musl": ["@napi-rs/nice-linux-x64-musl@1.1.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xScCGnyj/oppsNPMnevsBe3pvNaoK7FGvMjT35riz9YdhB2WtTG47ZlbxtOLpjeO9SqqQ2J2igCmz6IJOD5JYw=="], + + "@napi-rs/nice-openharmony-arm64": ["@napi-rs/nice-openharmony-arm64@1.1.1", "", { "os": "none", "cpu": "arm64" }, "sha512-6uJPRVwVCLDeoOaNyeiW0gp2kFIM4r7PL2MczdZQHkFi9gVlgm+Vn+V6nTWRcu856mJ2WjYJiumEajfSm7arPQ=="], + + "@napi-rs/nice-win32-arm64-msvc": ["@napi-rs/nice-win32-arm64-msvc@1.1.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-uoTb4eAvM5B2aj/z8j+Nv8OttPf2m+HVx3UjA5jcFxASvNhQriyCQF1OB1lHL43ZhW+VwZlgvjmP5qF3+59atA=="], + + "@napi-rs/nice-win32-ia32-msvc": ["@napi-rs/nice-win32-ia32-msvc@1.1.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-CNQqlQT9MwuCsg1Vd/oKXiuH+TcsSPJmlAFc5frFyX/KkOh0UpBLEj7aoY656d5UKZQMQFP7vJNa1DNUNORvug=="], + + "@napi-rs/nice-win32-x64-msvc": ["@napi-rs/nice-win32-x64-msvc@1.1.1", "", { "os": "win32", "cpu": "x64" }, "sha512-vB+4G/jBQCAh0jelMTY3+kgFy00Hlx2f2/1zjMoH821IbplbWZOkLiTYXQkygNTzQJTq5cvwBDgn2ppHD+bglQ=="], + + "@prisma/client": ["@prisma/client@6.16.2", "", { "peerDependencies": { "prisma": "*", "typescript": ">=5.1.0" }, "optionalPeers": ["typescript"] }, "sha512-E00PxBcalMfYO/TWnXobBVUai6eW/g5OsifWQsQDzJYm7yaY+IRLo7ZLsaefi0QkTpxfuhFcQ/w180i6kX3iJw=="], + + "@prisma/config": ["@prisma/config@6.16.2", "", { "dependencies": { "c12": "3.1.0", "deepmerge-ts": "7.1.5", "effect": "3.16.12", "empathic": "2.0.0" } }, "sha512-mKXSUrcqXj0LXWPmJsK2s3p9PN+aoAbyMx7m5E1v1FufofR1ZpPoIArjjzOIm+bJRLLvYftoNYLx1tbHgF9/yg=="], + + "@prisma/debug": ["@prisma/debug@6.16.2", "", {}, "sha512-bo4/gA/HVV6u8YK2uY6glhNsJ7r+k/i5iQ9ny/3q5bt9ijCj7WMPUwfTKPvtEgLP+/r26Z686ly11hhcLiQ8zA=="], + + "@prisma/engines": ["@prisma/engines@6.16.2", "", { "dependencies": { "@prisma/debug": "6.16.2", "@prisma/engines-version": "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43", "@prisma/fetch-engine": "6.16.2", "@prisma/get-platform": "6.16.2" } }, "sha512-7yf3AjfPUgsg/l7JSu1iEhsmZZ/YE00yURPjTikqm2z4btM0bCl2coFtTGfeSOWbQMmq45Jab+53yGUIAT1sjA=="], + + "@prisma/engines-version": ["@prisma/engines-version@6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43", "", {}, "sha512-ThvlDaKIVrnrv97ujNFDYiQbeMQpLa0O86HFA2mNoip4mtFqM7U5GSz2ie1i2xByZtvPztJlNRgPsXGeM/kqAA=="], + + "@prisma/fetch-engine": ["@prisma/fetch-engine@6.16.2", "", { "dependencies": { "@prisma/debug": "6.16.2", "@prisma/engines-version": "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43", "@prisma/get-platform": "6.16.2" } }, "sha512-wPnZ8DMRqpgzye758ZvfAMiNJRuYpz+rhgEBZi60ZqDIgOU2694oJxiuu3GKFeYeR/hXxso4/2oBC243t/whxQ=="], + + "@prisma/get-platform": ["@prisma/get-platform@6.16.2", "", { "dependencies": { "@prisma/debug": "6.16.2" } }, "sha512-U/P36Uke5wS7r1+omtAgJpEB94tlT4SdlgaeTc6HVTTT93pXj7zZ+B/cZnmnvjcNPfWddgoDx8RLjmQwqGDYyA=="], + + "@scarf/scarf": ["@scarf/scarf@1.4.0", "", {}, "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ=="], + + "@sindresorhus/is": ["@sindresorhus/is@5.6.0", "", {}, "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g=="], + + "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], + + "@swc/cli": ["@swc/cli@0.7.8", "", { "dependencies": { "@swc/counter": "^0.1.3", "@xhmikosr/bin-wrapper": "^13.0.5", "commander": "^8.3.0", "minimatch": "^9.0.3", "piscina": "^4.3.1", "semver": "^7.3.8", "slash": "3.0.0", "source-map": "^0.7.3", "tinyglobby": "^0.2.13" }, "peerDependencies": { "@swc/core": "^1.2.66", "chokidar": "^4.0.1" }, "bin": { "spack": "bin/spack.js", "swc": "bin/swc.js", "swcx": "bin/swcx.js" } }, "sha512-27Ov4rm0s2C6LLX+NDXfDVB69LGs8K94sXtFhgeUyQ4DBywZuCgTBu2loCNHRr8JhT9DeQvJM5j9FAu/THbo4w=="], + + "@swc/core": ["@swc/core@1.13.5", "", { "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.24" }, "optionalDependencies": { "@swc/core-darwin-arm64": "1.13.5", "@swc/core-darwin-x64": "1.13.5", "@swc/core-linux-arm-gnueabihf": "1.13.5", "@swc/core-linux-arm64-gnu": "1.13.5", "@swc/core-linux-arm64-musl": "1.13.5", "@swc/core-linux-x64-gnu": "1.13.5", "@swc/core-linux-x64-musl": "1.13.5", "@swc/core-win32-arm64-msvc": "1.13.5", "@swc/core-win32-ia32-msvc": "1.13.5", "@swc/core-win32-x64-msvc": "1.13.5" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" }, "optionalPeers": ["@swc/helpers"] }, "sha512-WezcBo8a0Dg2rnR82zhwoR6aRNxeTGfK5QCD6TQ+kg3xx/zNT02s/0o+81h/3zhvFSB24NtqEr8FTw88O5W/JQ=="], + + "@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.13.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-lKNv7SujeXvKn16gvQqUQI5DdyY8v7xcoO3k06/FJbHJS90zEwZdQiMNRiqpYw/orU543tPaWgz7cIYWhbopiQ=="], + + "@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.13.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-ILd38Fg/w23vHb0yVjlWvQBoE37ZJTdlLHa8LRCFDdX4WKfnVBiblsCU9ar4QTMNdeTBEX9iUF4IrbNWhaF1Ng=="], + + "@swc/core-linux-arm-gnueabihf": ["@swc/core-linux-arm-gnueabihf@1.13.5", "", { "os": "linux", "cpu": "arm" }, "sha512-Q6eS3Pt8GLkXxqz9TAw+AUk9HpVJt8Uzm54MvPsqp2yuGmY0/sNaPPNVqctCX9fu/Nu8eaWUen0si6iEiCsazQ=="], + + "@swc/core-linux-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.13.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-aNDfeN+9af+y+M2MYfxCzCy/VDq7Z5YIbMqRI739o8Ganz6ST+27kjQFd8Y/57JN/hcnUEa9xqdS3XY7WaVtSw=="], + + "@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.13.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-9+ZxFN5GJag4CnYnq6apKTnnezpfJhCumyz0504/JbHLo+Ue+ZtJnf3RhyA9W9TINtLE0bC4hKpWi8ZKoETyOQ=="], + + "@swc/core-linux-x64-gnu": ["@swc/core-linux-x64-gnu@1.13.5", "", { "os": "linux", "cpu": "x64" }, "sha512-WD530qvHrki8Ywt/PloKUjaRKgstQqNGvmZl54g06kA+hqtSE2FTG9gngXr3UJxYu/cNAjJYiBifm7+w4nbHbA=="], + + "@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.13.5", "", { "os": "linux", "cpu": "x64" }, "sha512-Luj8y4OFYx4DHNQTWjdIuKTq2f5k6uSXICqx+FSabnXptaOBAbJHNbHT/06JZh6NRUouaf0mYXN0mcsqvkhd7Q=="], + + "@swc/core-win32-arm64-msvc": ["@swc/core-win32-arm64-msvc@1.13.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-cZ6UpumhF9SDJvv4DA2fo9WIzlNFuKSkZpZmPG1c+4PFSEMy5DFOjBSllCvnqihCabzXzpn6ykCwBmHpy31vQw=="], + + "@swc/core-win32-ia32-msvc": ["@swc/core-win32-ia32-msvc@1.13.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-C5Yi/xIikrFUzZcyGj9L3RpKljFvKiDMtyDzPKzlsDrKIw2EYY+bF88gB6oGY5RGmv4DAX8dbnpRAqgFD0FMEw=="], + + "@swc/core-win32-x64-msvc": ["@swc/core-win32-x64-msvc@1.13.5", "", { "os": "win32", "cpu": "x64" }, "sha512-YrKdMVxbYmlfybCSbRtrilc6UA8GF5aPmGKBdPvjrarvsmf4i7ZHGCEnLtfOMd3Lwbs2WUZq3WdMbozYeLU93Q=="], + + "@swc/counter": ["@swc/counter@0.1.3", "", {}, "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="], + + "@swc/types": ["@swc/types@0.1.25", "", { "dependencies": { "@swc/counter": "^0.1.3" } }, "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g=="], + + "@szmarczak/http-timer": ["@szmarczak/http-timer@5.0.1", "", { "dependencies": { "defer-to-connect": "^2.0.1" } }, "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw=="], + + "@tokenizer/inflate": ["@tokenizer/inflate@0.2.7", "", { "dependencies": { "debug": "^4.4.0", "fflate": "^0.8.2", "token-types": "^6.0.0" } }, "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg=="], + + "@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="], + + "@types/body-parser": ["@types/body-parser@1.19.6", "", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g=="], + + "@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="], + + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@types/express": ["@types/express@5.0.3", "", { "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^5.0.0", "@types/serve-static": "*" } }, "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw=="], + + "@types/express-serve-static-core": ["@types/express-serve-static-core@5.0.7", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ=="], + + "@types/http-cache-semantics": ["@types/http-cache-semantics@4.0.4", "", {}, "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA=="], + + "@types/http-errors": ["@types/http-errors@2.0.5", "", {}, "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg=="], + + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + + "@types/mime": ["@types/mime@1.3.5", "", {}, "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="], + + "@types/node": ["@types/node@24.5.2", "", { "dependencies": { "undici-types": "~7.12.0" } }, "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ=="], + + "@types/qs": ["@types/qs@6.14.0", "", {}, "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ=="], + + "@types/range-parser": ["@types/range-parser@1.2.7", "", {}, "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="], + + "@types/send": ["@types/send@0.17.5", "", { "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w=="], + + "@types/serve-static": ["@types/serve-static@1.15.8", "", { "dependencies": { "@types/http-errors": "*", "@types/node": "*", "@types/send": "*" } }, "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg=="], + + "@xhmikosr/archive-type": ["@xhmikosr/archive-type@7.1.0", "", { "dependencies": { "file-type": "^20.5.0" } }, "sha512-xZEpnGplg1sNPyEgFh0zbHxqlw5dtYg6viplmWSxUj12+QjU9SKu3U/2G73a15pEjLaOqTefNSZ1fOPUOT4Xgg=="], + + "@xhmikosr/bin-check": ["@xhmikosr/bin-check@7.1.0", "", { "dependencies": { "execa": "^5.1.1", "isexe": "^2.0.0" } }, "sha512-y1O95J4mnl+6MpVmKfMYXec17hMEwE/yeCglFNdx+QvLLtP0yN4rSYcbkXnth+lElBuKKek2NbvOfOGPpUXCvw=="], + + "@xhmikosr/bin-wrapper": ["@xhmikosr/bin-wrapper@13.2.0", "", { "dependencies": { "@xhmikosr/bin-check": "^7.1.0", "@xhmikosr/downloader": "^15.2.0", "@xhmikosr/os-filter-obj": "^3.0.0", "bin-version-check": "^5.1.0" } }, "sha512-t9U9X0sDPRGDk5TGx4dv5xiOvniVJpXnfTuynVKwHgtib95NYEw4MkZdJqhoSiz820D9m0o6PCqOPMXz0N9fIw=="], + + "@xhmikosr/decompress": ["@xhmikosr/decompress@10.2.0", "", { "dependencies": { "@xhmikosr/decompress-tar": "^8.1.0", "@xhmikosr/decompress-tarbz2": "^8.1.0", "@xhmikosr/decompress-targz": "^8.1.0", "@xhmikosr/decompress-unzip": "^7.1.0", "graceful-fs": "^4.2.11", "strip-dirs": "^3.0.0" } }, "sha512-MmDBvu0+GmADyQWHolcZuIWffgfnuTo4xpr2I/Qw5Ox0gt+e1Be7oYqJM4te5ylL6mzlcoicnHVDvP27zft8tg=="], + + "@xhmikosr/decompress-tar": ["@xhmikosr/decompress-tar@8.1.0", "", { "dependencies": { "file-type": "^20.5.0", "is-stream": "^2.0.1", "tar-stream": "^3.1.7" } }, "sha512-m0q8x6lwxenh1CrsTby0Jrjq4vzW/QU1OLhTHMQLEdHpmjR1lgahGz++seZI0bXF3XcZw3U3xHfqZSz+JPP2Gg=="], + + "@xhmikosr/decompress-tarbz2": ["@xhmikosr/decompress-tarbz2@8.1.0", "", { "dependencies": { "@xhmikosr/decompress-tar": "^8.0.1", "file-type": "^20.5.0", "is-stream": "^2.0.1", "seek-bzip": "^2.0.0", "unbzip2-stream": "^1.4.3" } }, "sha512-aCLfr3A/FWZnOu5eqnJfme1Z1aumai/WRw55pCvBP+hCGnTFrcpsuiaVN5zmWTR53a8umxncY2JuYsD42QQEbw=="], + + "@xhmikosr/decompress-targz": ["@xhmikosr/decompress-targz@8.1.0", "", { "dependencies": { "@xhmikosr/decompress-tar": "^8.0.1", "file-type": "^20.5.0", "is-stream": "^2.0.1" } }, "sha512-fhClQ2wTmzxzdz2OhSQNo9ExefrAagw93qaG1YggoIz/QpI7atSRa7eOHv4JZkpHWs91XNn8Hry3CwUlBQhfPA=="], + + "@xhmikosr/decompress-unzip": ["@xhmikosr/decompress-unzip@7.1.0", "", { "dependencies": { "file-type": "^20.5.0", "get-stream": "^6.0.1", "yauzl": "^3.1.2" } }, "sha512-oqTYAcObqTlg8owulxFTqiaJkfv2SHsxxxz9Wg4krJAHVzGWlZsU8tAB30R6ow+aHrfv4Kub6WQ8u04NWVPUpA=="], + + "@xhmikosr/downloader": ["@xhmikosr/downloader@15.2.0", "", { "dependencies": { "@xhmikosr/archive-type": "^7.1.0", "@xhmikosr/decompress": "^10.2.0", "content-disposition": "^0.5.4", "defaults": "^2.0.2", "ext-name": "^5.0.0", "file-type": "^20.5.0", "filenamify": "^6.0.0", "get-stream": "^6.0.1", "got": "^13.0.0" } }, "sha512-lAqbig3uRGTt0sHNIM4vUG9HoM+mRl8K28WuYxyXLCUT6pyzl4Y4i0LZ3jMEsCYZ6zjPZbO9XkG91OSTd4si7g=="], + + "@xhmikosr/os-filter-obj": ["@xhmikosr/os-filter-obj@3.0.0", "", { "dependencies": { "arch": "^3.0.0" } }, "sha512-siPY6BD5dQ2SZPl3I0OZBHL27ZqZvLEosObsZRQ1NUB8qcxegwt0T9eKtV96JMFQpIz1elhkzqOg4c/Ri6Dp9A=="], + + "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="], + + "acorn": ["acorn@7.4.1", "", { "bin": "bin/acorn" }, "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A=="], + + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + + "ajv": ["ajv@6.12.6", "", { "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" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + + "ansi-escapes": ["ansi-escapes@7.1.1", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q=="], + + "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], + + "arch": ["arch@3.0.0", "", {}, "sha512-AmIAC+Wtm2AU8lGfTtHsw0Y9Qtftx2YXEEtiBP10xFUtMOA+sHHx6OAddyL52mUKh1vsXQ6/w1mVDptZCyUt4Q=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "b4a": ["b4a@1.7.2", "", { "peerDependencies": { "react-native-b4a": "*" }, "optionalPeers": ["react-native-b4a"] }, "sha512-DyUOdz+E8R6+sruDpQNOaV0y/dBbV6X/8ZkxrDcR0Ifc3BgKlpgG0VAtfOozA0eMtJO5GGe9FsZhueLs00pTww=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "bare-events": ["bare-events@2.7.0", "", {}, "sha512-b3N5eTW1g7vXkw+0CXh/HazGTcO5KYuu/RCNaJbDMPI6LHDi+7qe8EmxKUVe1sUbY2KZOVZFyj62x0OEz9qyAA=="], + + "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], + + "bin-version": ["bin-version@6.0.0", "", { "dependencies": { "execa": "^5.0.0", "find-versions": "^5.0.0" } }, "sha512-nk5wEsP4RiKjG+vF+uG8lFsEn4d7Y6FVDamzzftSunXOoOcOOkzcWdKVlGgFFwlUQCj63SgnUkLLGF8v7lufhw=="], + + "bin-version-check": ["bin-version-check@5.1.0", "", { "dependencies": { "bin-version": "^6.0.0", "semver": "^7.5.3", "semver-truncate": "^3.0.0" } }, "sha512-bYsvMqJ8yNGILLz1KP9zKLzQ6YpljV3ln1gqhuLkUtyfGi3qXKGuK2p+U4NAvjVFzDFiBBtOpCOSFNuYYEGZ5g=="], + + "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], + + "body-parser": ["body-parser@2.2.0", "", { "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" } }, "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg=="], + + "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], + + "buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="], + + "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], + + "c12": ["c12@3.1.0", "", { "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" }, "optionalPeers": ["magicast"] }, "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw=="], + + "cacheable-lookup": ["cacheable-lookup@7.0.0", "", {}, "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w=="], + + "cacheable-request": ["cacheable-request@10.2.14", "", { "dependencies": { "@types/http-cache-semantics": "^4.0.2", "get-stream": "^6.0.1", "http-cache-semantics": "^4.1.1", "keyv": "^4.5.3", "mimic-response": "^4.0.0", "normalize-url": "^8.0.0", "responselike": "^3.0.0" } }, "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ=="], + + "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], + + "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], + + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "chokidar": ["chokidar@3.6.0", "", { "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" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], + + "citty": ["citty@0.1.6", "", { "dependencies": { "consola": "^3.2.3" } }, "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ=="], + + "cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="], + + "cli-truncate": ["cli-truncate@5.1.0", "", { "dependencies": { "slice-ansi": "^7.1.0", "string-width": "^8.0.0" } }, "sha512-7JDGG+4Zp0CsknDCedl0DYdaeOhc46QNpXi3NLQblkZpXXgA6LncLDUUyvrjSvZeF3VRQa+KiMGomazQrC1V8g=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], + + "commander": ["commander@14.0.1", "", {}, "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + + "confbox": ["confbox@0.2.2", "", {}, "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="], + + "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], + + "content-disposition": ["content-disposition@1.0.0", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg=="], + + "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], + + "cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], + + "cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="], + + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + + "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], + + "deepmerge-ts": ["deepmerge-ts@7.1.5", "", {}, "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw=="], + + "defaults": ["defaults@2.0.2", "", {}, "sha512-cuIw0PImdp76AOfgkjbW4VhQODRmNNcKR73vdCH5cLd/ifj7aamfoXvYgfGkEAjNJZ3ozMIy9Gu2LutUkGEPbA=="], + + "defer-to-connect": ["defer-to-connect@2.0.1", "", {}, "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg=="], + + "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], + + "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="], + + "destr": ["destr@2.0.5", "", {}, "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA=="], + + "dotenv": ["dotenv@17.2.2", "", {}, "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q=="], + + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + + "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], + + "effect": ["effect@3.16.12", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg=="], + + "emoji-regex": ["emoji-regex@10.5.0", "", {}, "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg=="], + + "empathic": ["empathic@2.0.0", "", {}, "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA=="], + + "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], + + "environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="], + + "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], + + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], + + "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], + + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + + "eslint": ["eslint@9.36.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.1", "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.36.0", "@eslint/plugin-kit": "^0.3.5", "@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" }, "peerDependencies": { "jiti": "*" }, "bin": "bin/eslint.js" }, "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ=="], + + "eslint-config-prettier": ["eslint-config-prettier@10.1.8", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w=="], + + "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], + + "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + + "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], + + "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], + + "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + + "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], + + "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + + "events-universal": ["events-universal@1.0.1", "", { "dependencies": { "bare-events": "^2.7.0" } }, "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw=="], + + "execa": ["execa@5.1.1", "", { "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" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="], + + "express": ["express@5.1.0", "", { "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" } }, "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA=="], + + "exsolve": ["exsolve@1.0.7", "", {}, "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw=="], + + "ext-list": ["ext-list@2.2.2", "", { "dependencies": { "mime-db": "^1.28.0" } }, "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA=="], + + "ext-name": ["ext-name@5.0.0", "", { "dependencies": { "ext-list": "^2.0.0", "sort-keys-length": "^1.0.0" } }, "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ=="], + + "fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "^6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-fifo": ["fast-fifo@1.3.2", "", {}, "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ=="], + + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + + "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], + + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" } }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + + "fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="], + + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + + "file-type": ["file-type@20.5.0", "", { "dependencies": { "@tokenizer/inflate": "^0.2.6", "strtok3": "^10.2.0", "token-types": "^6.0.0", "uint8array-extras": "^1.4.0" } }, "sha512-BfHZtG/l9iMm4Ecianu7P8HRD2tBHLtjXinm4X62XBOYzi7CYA7jyqfJzOvXHqzVrVPYqBo2/GvbARMaaJkKVg=="], + + "filename-reserved-regex": ["filename-reserved-regex@3.0.0", "", {}, "sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw=="], + + "filenamify": ["filenamify@6.0.0", "", { "dependencies": { "filename-reserved-regex": "^3.0.0" } }, "sha512-vqIlNogKeyD3yzrm0yhRMQg8hOVwYcYRfjEoODd49iCprMn4HL85gK3HcykQE53EPIpX3HcAbGA5ELQv216dAQ=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "finalhandler": ["finalhandler@2.1.0", "", { "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" } }, "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q=="], + + "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], + + "find-versions": ["find-versions@5.1.0", "", { "dependencies": { "semver-regex": "^4.0.5" } }, "sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg=="], + + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], + + "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], + + "form-data-encoder": ["form-data-encoder@2.1.4", "", {}, "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw=="], + + "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], + + "fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="], + + "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="], + + "get-intrinsic": ["get-intrinsic@1.3.0", "", { "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" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], + + "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + + "get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="], + + "giget": ["giget@2.0.0", "", { "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": "dist/cli.mjs" }, "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA=="], + + "glob": ["glob@7.2.3", "", { "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" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], + + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + + "got": ["got@13.0.0", "", { "dependencies": { "@sindresorhus/is": "^5.2.0", "@szmarczak/http-timer": "^5.0.1", "cacheable-lookup": "^7.0.0", "cacheable-request": "^10.2.8", "decompress-response": "^6.0.0", "form-data-encoder": "^2.1.2", "get-stream": "^6.0.1", "http2-wrapper": "^2.1.10", "lowercase-keys": "^3.0.0", "p-cancelable": "^3.0.0", "responselike": "^3.0.0" } }, "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], + + "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], + + "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + + "http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="], + + "http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="], + + "http2-wrapper": ["http2-wrapper@2.2.1", "", { "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.2.0" } }, "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ=="], + + "human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="], + + "husky": ["husky@9.1.7", "", { "bin": "bin.js" }, "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="], + + "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + + "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "ignore-by-default": ["ignore-by-default@1.0.1", "", {}, "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA=="], + + "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], + + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + + "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="], + + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + + "inspect-with-kind": ["inspect-with-kind@1.0.5", "", { "dependencies": { "kind-of": "^6.0.2" } }, "sha512-MAQUJuIo7Xqk8EVNP+6d3CKq9c80hi4tjIbIAT6lmGW9W6WzlHiu9PS8uSuUYU+Do+j1baiFp3H25XEVxDIG2g=="], + + "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], + + "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "is-plain-obj": ["is-plain-obj@1.1.0", "", {}, "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg=="], + + "is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="], + + "is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "jiti": ["jiti@2.6.0", "", { "bin": "lib/jiti-cli.mjs" }, "sha512-VXe6RjJkBPj0ohtqaO8vSWP3ZhAKo66fKrFNCll4BTcwljPLz03pCbaNKfzGP5MbrCYcbJ7v0nOYYwUzTEIdXQ=="], + + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": "bin/js-yaml.js" }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + + "json5": ["json5@2.2.3", "", { "bin": "lib/cli.js" }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + + "kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="], + + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], + + "lint-staged": ["lint-staged@16.2.0", "", { "dependencies": { "commander": "14.0.1", "listr2": "9.0.4", "micromatch": "4.0.8", "nano-spawn": "1.0.3", "pidtree": "0.6.0", "string-argv": "0.3.2", "yaml": "2.8.1" }, "bin": "bin/lint-staged.js" }, "sha512-spdYSOCQ2MdZ9CM1/bu/kDmaYGsrpNOeu1InFFV8uhv14x6YIubGxbCpSmGILFoxkiheNQPDXSg5Sbb5ZuVnug=="], + + "listr2": ["listr2@9.0.4", "", { "dependencies": { "cli-truncate": "^5.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" } }, "sha512-1wd/kpAdKRLwv7/3OKC8zZ5U8e/fajCfWMxacUvB79S5nLrYGPtUI/8chMQhn3LQjsRVErTb9i1ECAwW0ZIHnQ=="], + + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + + "log-update": ["log-update@6.1.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w=="], + + "lowercase-keys": ["lowercase-keys@3.0.0", "", {}, "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ=="], + + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], + + "media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="], + + "merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="], + + "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], + + "mime-types": ["mime-types@3.0.1", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA=="], + + "mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="], + + "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="], + + "mimic-response": ["mimic-response@4.0.0", "", {}, "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg=="], + + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "nano-spawn": ["nano-spawn@1.0.3", "", {}, "sha512-jtpsQDetTnvS2Ts1fiRdci5rx0VYws5jGyC+4IYOTnIQ/wwdf6JdomlHBwqC3bJYOvaKu0C2GSZ1A60anrYpaA=="], + + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + + "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], + + "node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="], + + "nodemon": ["nodemon@3.1.10", "", { "dependencies": { "chokidar": "^3.5.2", "debug": "^4", "ignore-by-default": "^1.0.1", "minimatch": "^3.1.2", "pstree.remy": "^1.1.8", "semver": "^7.5.3", "simple-update-notifier": "^2.0.0", "supports-color": "^5.5.0", "touch": "^3.1.0", "undefsafe": "^2.0.5" }, "bin": "bin/nodemon.js" }, "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw=="], + + "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], + + "normalize-url": ["normalize-url@8.1.0", "", {}, "sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w=="], + + "npm-run-path": ["npm-run-path@4.0.1", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="], + + "nypm": ["nypm@0.6.2", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.2", "pathe": "^2.0.3", "pkg-types": "^2.3.0", "tinyexec": "^1.0.1" }, "bin": "dist/cli.mjs" }, "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g=="], + + "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], + + "ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], + + "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="], + + "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + + "onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="], + + "optionator": ["optionator@0.9.4", "", { "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" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + + "p-cancelable": ["p-cancelable@3.0.0", "", {}, "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw=="], + + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], + + "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + + "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], + + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + + "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="], + + "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "pend": ["pend@1.2.0", "", {}, "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="], + + "perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="], + + "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "pidtree": ["pidtree@0.6.0", "", { "bin": "bin/pidtree.js" }, "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g=="], + + "piscina": ["piscina@4.9.2", "", { "optionalDependencies": { "@napi-rs/nice": "^1.0.1" } }, "sha512-Fq0FERJWFEUpB4eSY59wSNwXD4RYqR+nR/WiEVcZW8IWfVBxJJafcgTEZDQo8k3w0sUarJ8RyVbbUF4GQ2LGbQ=="], + + "pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="], + + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], + + "prettier": ["prettier@3.6.2", "", { "bin": "bin/prettier.cjs" }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], + + "prisma": ["prisma@6.16.2", "", { "dependencies": { "@prisma/config": "6.16.2", "@prisma/engines": "6.16.2" }, "peerDependencies": { "typescript": ">=5.1.0" }, "optionalPeers": ["typescript"], "bin": "build/index.js" }, "sha512-aRvldGE5UUJTtVmFiH3WfNFNiqFlAtePUxcI0UEGlnXCX7DqhiMT5TRYwncHFeA/Reca5W6ToXXyCMTeFPdSXA=="], + + "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], + + "pstree.remy": ["pstree.remy@1.1.8", "", {}, "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w=="], + + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + + "pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="], + + "qs": ["qs@6.14.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w=="], + + "quick-lru": ["quick-lru@5.1.1", "", {}, "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="], + + "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], + + "raw-body": ["raw-body@3.0.1", "", { "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.7.0", "unpipe": "1.0.0" } }, "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA=="], + + "rc9": ["rc9@2.1.2", "", { "dependencies": { "defu": "^6.1.4", "destr": "^2.0.3" } }, "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg=="], + + "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], + + "resolve-alpn": ["resolve-alpn@1.2.1", "", {}, "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="], + + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + + "responselike": ["responselike@3.0.0", "", { "dependencies": { "lowercase-keys": "^3.0.0" } }, "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg=="], + + "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], + + "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], + + "router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="], + + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + + "seek-bzip": ["seek-bzip@2.0.0", "", { "dependencies": { "commander": "^6.0.0" }, "bin": { "seek-bunzip": "bin/seek-bunzip", "seek-table": "bin/seek-bzip-table" } }, "sha512-SMguiTnYrhpLdk3PwfzHeotrcwi8bNV4iemL9tx9poR/yeaMYwB9VzR1w7b57DuWpuqR8n6oZboi0hj3AxZxQg=="], + + "semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + + "semver-regex": ["semver-regex@4.0.5", "", {}, "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw=="], + + "semver-truncate": ["semver-truncate@3.0.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-LJWA9kSvMolR51oDE6PN3kALBNaUdkxzAGcexw8gjMA8xr5zUqK0JiR3CgARSqanYF3Z1YHvsErb1KDgh+v7Rg=="], + + "send": ["send@1.2.0", "", { "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" } }, "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw=="], + + "serve-static": ["serve-static@2.2.0", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ=="], + + "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "side-channel": ["side-channel@1.1.0", "", { "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" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], + + "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], + + "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], + + "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "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" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], + + "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + + "simple-update-notifier": ["simple-update-notifier@2.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w=="], + + "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], + + "slice-ansi": ["slice-ansi@7.1.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w=="], + + "sort-keys": ["sort-keys@1.1.2", "", { "dependencies": { "is-plain-obj": "^1.0.0" } }, "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg=="], + + "sort-keys-length": ["sort-keys-length@1.0.1", "", { "dependencies": { "sort-keys": "^1.0.0" } }, "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw=="], + + "source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], + + "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], + + "streamx": ["streamx@2.23.0", "", { "dependencies": { "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" } }, "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg=="], + + "string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="], + + "string-width": ["string-width@8.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.0", "strip-ansi": "^7.1.0" } }, "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg=="], + + "strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], + + "strip-dirs": ["strip-dirs@3.0.0", "", { "dependencies": { "inspect-with-kind": "^1.0.5", "is-plain-obj": "^1.1.0" } }, "sha512-I0sdgcFTfKQlUPZyAqPJmSG3HLO9rWDFnxonnIbskYNM3DwFOeTNB5KzVq3dA1GdRAc/25b5Y7UO2TQfKWw4aQ=="], + + "strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="], + + "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + + "strtok3": ["strtok3@10.3.4", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg=="], + + "supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], + + "swagger-autogen": ["swagger-autogen@2.23.7", "", { "dependencies": { "acorn": "^7.4.1", "deepmerge": "^4.2.2", "glob": "^7.1.7", "json5": "^2.2.3" } }, "sha512-vr7uRmuV0DCxWc0wokLJAwX3GwQFJ0jwN+AWk0hKxre2EZwusnkGSGdVFd82u7fQLgwSTnbWkxUL7HXuz5LTZQ=="], + + "swagger-ui-dist": ["swagger-ui-dist@5.29.0", "", { "dependencies": { "@scarf/scarf": "=1.4.0" } }, "sha512-gqs7Md3AxP4mbpXAq31o5QW+wGUZsUzVatg70yXpUR245dfIis5jAzufBd+UQM/w2xSfrhvA1eqsrgnl2PbezQ=="], + + "swagger-ui-express": ["swagger-ui-express@5.0.1", "", { "dependencies": { "swagger-ui-dist": ">=5.0.0" }, "peerDependencies": { "express": ">=4.0.0 || >=5.0.0-beta" } }, "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA=="], + + "tar-stream": ["tar-stream@3.1.7", "", { "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ=="], + + "text-decoder": ["text-decoder@1.2.3", "", { "dependencies": { "b4a": "^1.6.4" } }, "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA=="], + + "through": ["through@2.3.8", "", {}, "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="], + + "tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="], + + "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], + + "token-types": ["token-types@6.1.1", "", { "dependencies": { "@borewit/text-codec": "^0.1.0", "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ=="], + + "touch": ["touch@3.1.1", "", { "bin": { "nodetouch": "bin/nodetouch.js" } }, "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA=="], + + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + + "type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="], + + "uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="], + + "unbzip2-stream": ["unbzip2-stream@1.4.3", "", { "dependencies": { "buffer": "^5.2.1", "through": "^2.3.8" } }, "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg=="], + + "undefsafe": ["undefsafe@2.0.5", "", {}, "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA=="], + + "undici-types": ["undici-types@7.12.0", "", {}, "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ=="], + + "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], + + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + + "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + + "wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="], + + "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], + + "yaml": ["yaml@2.8.1", "", { "bin": "bin.mjs" }, "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw=="], + + "yauzl": ["yauzl@3.2.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "pend": "~1.2.0" } }, "sha512-Ow9nuGZE+qp1u4JIPvg+uCiUr7xGQWdff7JQSk5VGYTAZMDe2q8lxJ10ygv10qmSj031Ty/6FNJpLO4o1Sgc+w=="], + + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + + "zod": ["zod@4.1.11", "", {}, "sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg=="], + + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "@eslint/config-array/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "@eslint/eslintrc/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "@swc/cli/chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], + + "@swc/cli/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="], + + "@swc/cli/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "@xhmikosr/downloader/content-disposition": ["content-disposition@0.5.4", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ=="], + + "c12/chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], + + "c12/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], + + "chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "decompress-response/mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="], + + "espree/acorn": ["acorn@8.15.0", "", { "bin": "bin/acorn" }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + + "fdir/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + + "glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "http-errors/statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="], + + "nodemon/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "raw-body/iconv-lite": ["iconv-lite@0.7.0", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ=="], + + "restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], + + "restore-cursor/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "seek-bzip/commander": ["commander@6.2.1", "", {}, "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA=="], + + "slice-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + + "tinyglobby/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + + "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + + "wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], + + "@eslint/config-array/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + + "@eslint/eslintrc/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + + "@swc/cli/chokidar/readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], + + "@swc/cli/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "c12/chokidar/readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], + + "chalk/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "glob/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + + "nodemon/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + } +} diff --git a/eslint.confg.js b/eslint.confg.js index 8256d89..516309a 100644 --- a/eslint.confg.js +++ b/eslint.confg.js @@ -1,23 +1,23 @@ -import js from '@eslint/js'; +import js from "@eslint/js"; +import eslintConfigPrettier from "eslint-config-prettier/flat"; export default [ js.configs.recommended, { languageOptions: { ecmaVersion: 2024, - sourceType: 'module', + sourceType: "module", globals: { - console: 'readonly', - process: 'readonly', + console: "readonly", + process: "readonly", }, }, rules: { - 'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], - 'no-console': 'off', - 'prefer-const': 'error', - 'no-var': 'error', - semi: ['error', 'always'], - quotes: ['error', 'single'], + "no-unused-vars": ["warn", { argsIgnorePattern: "^_" }], + "no-console": "off", + "prefer-const": "error", + "no-var": "error", }, }, -]; \ No newline at end of file + eslintConfigPrettier, +]; diff --git a/package.json b/package.json index f528e2c..5b94264 100644 --- a/package.json +++ b/package.json @@ -13,11 +13,12 @@ "prisma": "dotenv -e ./env/.env.development -- prisma", "db:push": "npm run prisma -- db push --schema ./prisma/schema", "migrate:dev": "npm run prisma -- migrate dev --schema ./prisma/schema", + "migrate:deploy": "npm run prisma -- migrate deploy --schema ./prisma/schema", "migrate:reset": "npm run prisma -- migrate reset --schema ./prisma/schema", "studio": "npm run prisma -- studio --schema ./prisma/schema" }, "lint-staged": { - "**/*.ts": [ + "**/*.(js.jsx.ts.tsx)": [ "prettier --write", "eslint --fix" ] @@ -54,6 +55,7 @@ "@types/express": "^5.0.3", "@types/node": "^24.5.2", "eslint": "^9.36.0", + "eslint-config-prettier": "^10.1.8", "husky": "^9.1.7", "lint-staged": "^16.2.0", "nodemon": "^3.1.10", diff --git a/prittier..config.js b/prittier..config.js new file mode 100644 index 0000000..07caad1 --- /dev/null +++ b/prittier..config.js @@ -0,0 +1,11 @@ +const config = { + printWidth: 80, + tabWidth: 2, + bracketSpacing: true, + arrowParens: "always", + trailingComma: "all", + semi: true, + singleQuote: true, +}; + +export default config; From 78d8f7e15daa12a359c518cf8d3362e34eda14dd Mon Sep 17 00:00:00 2001 From: rklpoi5678 Date: Sun, 5 Oct 2025 21:54:54 +0900 Subject: [PATCH 09/13] =?UTF-8?q?Refactor:=20=EA=B3=B5=ED=86=B5=EB=90=9C?= =?UTF-8?q?=20=EC=97=90=EB=9F=AC=EC=BD=94=EB=93=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/constants/errorMessage.js | 3 +++ src/common/constants/httpStatus.js | 19 +++++++++++++++++++ src/common/constants/index.js | 2 ++ src/{common => controllers/v1}/dto/Items.js | 2 +- src/controllers/v1/item.controller.js | 21 +++++++++++++-------- src/routes/v1/items.js | 2 +- 6 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 src/common/constants/errorMessage.js create mode 100644 src/common/constants/httpStatus.js create mode 100644 src/common/constants/index.js rename src/{common => controllers/v1}/dto/Items.js (98%) diff --git a/src/common/constants/errorMessage.js b/src/common/constants/errorMessage.js new file mode 100644 index 0000000..c6e39b2 --- /dev/null +++ b/src/common/constants/errorMessage.js @@ -0,0 +1,3 @@ +// Items +export const NOT_FOUND_ITEM = "존재하지 않는 아이템입니다."; +export const FAILED_UPDATE_ITEM = "업데이트에 실패하였습니다."; diff --git a/src/common/constants/httpStatus.js b/src/common/constants/httpStatus.js new file mode 100644 index 0000000..742080b --- /dev/null +++ b/src/common/constants/httpStatus.js @@ -0,0 +1,19 @@ +const OK = 200; +const CREATED = 201; +const BAD_REQUEST = 400; +const UNAUTHORIZED = 401; +const FORBIDDEN = 403; +const NOT_FOUND = 404; +const CONFLICT = 409; +const INTERNAL_SERVER_ERROR = 500; + +export const HttpStatus = { + OK, + CREATED, + BAD_REQUEST, + UNAUTHORIZED, + FORBIDDEN, + NOT_FOUND, + CONFLICT, + INTERNAL_SERVER_ERROR, +}; diff --git a/src/common/constants/index.js b/src/common/constants/index.js new file mode 100644 index 0000000..e82df66 --- /dev/null +++ b/src/common/constants/index.js @@ -0,0 +1,2 @@ +export * from "./httpStatus"; +export * from "./errorMessage"; diff --git a/src/common/dto/Items.js b/src/controllers/v1/dto/Items.js similarity index 98% rename from src/common/dto/Items.js rename to src/controllers/v1/dto/Items.js index 79d197a..6dae270 100644 --- a/src/common/dto/Items.js +++ b/src/controllers/v1/dto/Items.js @@ -5,4 +5,4 @@ export const getItemsSchema = z.object({ limit: z.string().default("10"), keyword: z.string().default(""), orderBy: z.enum(["recent", "favorite"]).default("recent"), -}); \ No newline at end of file +}); diff --git a/src/controllers/v1/item.controller.js b/src/controllers/v1/item.controller.js index 2546a24..2ba2556 100644 --- a/src/controllers/v1/item.controller.js +++ b/src/controllers/v1/item.controller.js @@ -1,5 +1,10 @@ import { prisma } from "../../db/index.js"; import { NotFoundException } from "../../common/exceptions/notFoundException.js"; +import { HttpStatus } from "../../common/constants/httpStatus.js"; +import { + FAILED_UPDATE_ITEM, + NOT_FOUND_ITEM, +} from "../../common/constants/errorMessage.js"; // "get AllItems" export const getItems = async (req, res, next) => { @@ -34,7 +39,7 @@ export const getItems = async (req, res, next) => { take: limit, }); - res.json({ + res.status(HttpStatus.OK).json({ success: true, message: "sucess get products", data: product, @@ -60,9 +65,9 @@ export const getItemById = async (req, res, next) => { }); if (!item) { - throw new NotFoundException("not found item"); + throw new NotFoundException(NOT_FOUND_ITEM); } - res.json({ + res.status(HttpStatus.OK).json({ sucess: true, message: "fined items", data: item, @@ -86,7 +91,7 @@ export const createItem = async (req, res, next) => { tags, }, }); - res.status(201).json({ + res.status(HttpStatus.CREATED).json({ success: true, message: "success create Item", data: newItem, @@ -106,9 +111,9 @@ export const deleteItem = async (req, res, next) => { }); if (!deleteItem) { - throw new NotFoundException("not found item"); + throw new NotFoundException(NOT_FOUND_ITEM); } - res.json({ + res.status(HttpStatus.OK).json({ success: true, message: "success delete item", }); @@ -135,10 +140,10 @@ export const patchItem = async (req, res, next) => { }); if (!updateItem) { - throw new NotFoundException("failed update item"); + throw new NotFoundException(FAILED_UPDATE_ITEM); } - res.json({ + res.status(HttpStatus.OK).json({ success: true, message: "success update item", data: updateItem, diff --git a/src/routes/v1/items.js b/src/routes/v1/items.js index aca6a61..1de40e0 100644 --- a/src/routes/v1/items.js +++ b/src/routes/v1/items.js @@ -1,7 +1,7 @@ import express from "express"; import { validateProduct } from "../../middlewares/validateProduct.js"; import { validateQuery } from "../../middlewares/validate.js"; -import { getItemsSchema } from "../../common/dto/Items.js"; +import { getItemsSchema } from "../../controllers/v1/dto/Items.js"; import { createItem, deleteItem, From 43fa0ed5dc3cde9360980de349577d20620cd252 Mon Sep 17 00:00:00 2001 From: rklpoi5678 Date: Sun, 5 Oct 2025 22:07:28 +0900 Subject: [PATCH 10/13] =?UTF-8?q?Refactor:=20Articles=EB=8F=84=20=EA=B3=B5?= =?UTF-8?q?=ED=86=B5=EB=90=9C=20=EC=97=90=EB=9F=AC=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/constants/errorMessage.js | 6 ++++++ src/middlewares/validate.js | 8 ++++---- src/routes/v1/articles.js | 29 +++++++++++++++++----------- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/common/constants/errorMessage.js b/src/common/constants/errorMessage.js index c6e39b2..7a37784 100644 --- a/src/common/constants/errorMessage.js +++ b/src/common/constants/errorMessage.js @@ -1,3 +1,9 @@ // Items export const NOT_FOUND_ITEM = "존재하지 않는 아이템입니다."; export const FAILED_UPDATE_ITEM = "업데이트에 실패하였습니다."; + +// Article +export const NOT_FOUND_ARTICLE = "해당게시물을 찾을수없습니다."; +export const FAILED_UPDATE_ARTICLE = "수정에 실패하였습니다."; +export const FAILED_UPDATE_ARTICLE_VIEW = "뷰 업데이트에 실패하였습니다."; +export const FAILED_DELETE_ARTICLE = "삭제를 할수없습니다."; diff --git a/src/middlewares/validate.js b/src/middlewares/validate.js index ad1725c..1e63b98 100644 --- a/src/middlewares/validate.js +++ b/src/middlewares/validate.js @@ -1,16 +1,16 @@ import z from "zod"; +import { HttpStatus } from "../common/constants/httpStatus.js"; export const validateQuery = (schema) => (req, res, next) => { try { schema.parse(req.query); } catch (error) { - if (error instanceof z.ZodError) { - return res.status(400).json({ + if (error instanceof z.ZodError) + return res.status(HttpStatus.BAD_REQUEST).json({ success: false, message: "Failed validateQuery", errors: error.issues, }); - } next(error); } next(); @@ -21,7 +21,7 @@ export const validateBody = (schema) => (req, res, next) => { schema.parse(req.body); } catch (error) { if (error instanceof z.ZodError) { - res.status(400).json({ + res.status(HttpStatus.BAD_REQUEST).json({ success: false, message: "Faild validateBody", errors: error.issues, diff --git a/src/routes/v1/articles.js b/src/routes/v1/articles.js index 646b0df..9edb56e 100644 --- a/src/routes/v1/articles.js +++ b/src/routes/v1/articles.js @@ -1,6 +1,13 @@ import express from "express"; import { prisma } from "../../db/index.js"; import { NotFoundException } from "../../common/exceptions/index.js"; +import { HttpStatus } from "../../common/constants/httpStatus.js"; +import { + FAILED_DELETE_ARTICLE, + FAILED_UPDATE_ARTICLE, + FAILED_UPDATE_ARTICLE_VIEW, + NOT_FOUND_ARTICLE, +} from "../../common/constants/errorMessage.js"; export const articleRouter = express.Router(); @@ -44,7 +51,7 @@ articleRouter.get("/", async (req, res, next) => { take: limit, }); - res.status(200).json({ + res.status(HttpStatus.OK).json({ success: true, message: "success get articls", data: article, @@ -85,10 +92,10 @@ articleRouter.get("/:articleId", async (req, res, next) => { }); if (!article) { - throw new NotFoundException("해당게시물을 찾을수없습니다."); + throw new NotFoundException(NOT_FOUND_ARTICLE); } - res.status(200).json({ + res.status(HttpStatus.OK).json({ success: true, message: "success get article", data: article, @@ -112,7 +119,7 @@ articleRouter.post("/", async (req, res, next) => { }, }); - res.status(201).json({ + res.status(HttpStatus.CREATED).json({ success: true, message: "success create article", data: newArticle, @@ -138,10 +145,10 @@ articleRouter.patch("/:articleId", async (req, res, next) => { }); if (!updateArticle) { - throw new NotFoundException("수정에 실패하였습니다."); + throw new NotFoundException(FAILED_UPDATE_ARTICLE); } - res.status(200).json({ + res.status(HttpStatus.OK).json({ success: true, message: "success update article", data: updateArticle, @@ -166,10 +173,10 @@ articleRouter.patch("/:articleId/views", async (req, res, next) => { }); if (!updateArticle) { - throw new NotFoundException("수정에 실패하였습니다."); + throw new NotFoundException(FAILED_UPDATE_ARTICLE_VIEW); } - res.status(200).json({ + res.status(HttpStatus.OK).json({ success: true, message: "success update article", data: updateArticle, @@ -188,17 +195,17 @@ articleRouter.delete("/:articleId", async (req, res, next) => { }); if (!deleteArticle) { - throw new NotFoundException("게시물을 찾을 수 없습니다."); + throw new NotFoundException(NOT_FOUND_ARTICLE); } - res.status(200).json({ + res.status(HttpStatus.OK).json({ success: true, message: "success delete article", data: deleteArticle, }); } catch (error) { if (error.code === "P2025") { - next(new NotFoundException("Failed delete article")); + next(new NotFoundException(FAILED_DELETE_ARTICLE)); } else { next(error); } From b9bc8a6b850bace06f5c80d6346261cf807b681f Mon Sep 17 00:00:00 2001 From: rklpoi5678 Date: Sun, 5 Oct 2025 22:22:16 +0900 Subject: [PATCH 11/13] =?UTF-8?q?Refactor:=20=EB=9D=BC=EC=9A=B0=ED=84=B0?= =?UTF-8?q?=20Articles=EB=8F=84=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/v1/article.controller.js | 211 +++++++++++++++++++++++ src/routes/v1/articles.js | 210 ++-------------------- 2 files changed, 225 insertions(+), 196 deletions(-) create mode 100644 src/controllers/v1/article.controller.js diff --git a/src/controllers/v1/article.controller.js b/src/controllers/v1/article.controller.js new file mode 100644 index 0000000..82bf7d7 --- /dev/null +++ b/src/controllers/v1/article.controller.js @@ -0,0 +1,211 @@ +import { prisma } from "../../db/index.js"; +import { NotFoundException } from "../../common/exceptions/notFoundException.js"; +import { HttpStatus } from "../../common/constants/httpStatus.js"; +import { + NOT_FOUND_ARTICLE, + FAILED_UPDATE_ARTICLE, + FAILED_UPDATE_ARTICLE_VIEW, + FAILED_DELETE_ARTICLE, +} from "../../common/constants/errorMessage.js"; + +export const getArticles = async (req, res, next) => { + try { + const { + page: pageStr = 1, + limit: limitStr = 10, + keyword = "", + orderBy = "recent", + } = req.query; + + const page = parseInt(pageStr); + const limit = parseInt(limitStr); + const total = await prisma.article.count(); + const totalPage = Math.ceil(total / limit); + + const SORT_MAP = { + recent: { createdAt: "desc" }, + oldest: { createdAt: "asc" }, + }; + + const sortOptions = SORT_MAP[orderBy] ?? {}; + + const article = await prisma.article.findMany({ + where: { + OR: [ + { title: { contains: keyword, mode: "insensitive" } }, + { content: { contains: keyword, mode: "insensitive" } }, + ], + }, + include: { + author: { + include: { + userProfile: true, + }, + }, + }, + orderBy: sortOptions, + skip: limit * (page - 1), + take: limit, + }); + + res.status(HttpStatus.OK).json({ + success: true, + message: "success get articls", + data: article, + pagination: { + page, + limit, + total, + totalPage, + }, + }); + } catch (error) { + next(error); + return; + } +}; + +export const getArticleById = async (req, res, next) => { + try { + const { articleId } = req.params; + const article = await prisma.article.findUnique({ + where: { id: parseInt(articleId) }, + include: { + Comment: { + include: { + author: { + include: { + userProfile: true, + }, + }, + }, + }, + author: { + include: { + userProfile: true, + }, + }, + }, + }); + + if (!article) { + throw new NotFoundException(NOT_FOUND_ARTICLE); + } + + res.status(HttpStatus.OK).json({ + success: true, + message: "success get article", + data: article, + }); + } catch (error) { + next(error); + return; + } +}; + +export const createArticle = async (req, res, next) => { + try { + const { title, content, images } = req.body; + + // TODO: userId + const newArticle = await prisma.article.create({ + data: { + title, + content, + images, + }, + }); + + res.status(HttpStatus.CREATED).json({ + success: true, + message: "success create article", + data: newArticle, + }); + } catch (error) { + next(error); + return; + } +}; + +export const deleteArticle = async (req, res, next) => { + try { + const { articleId } = req.params; + const deleteArticle = await prisma.article.delete({ + where: { id: parseInt(articleId) }, + }); + + if (!deleteArticle) { + throw new NotFoundException(NOT_FOUND_ARTICLE); + } + + res.status(HttpStatus.OK).json({ + success: true, + message: "success delete article", + data: deleteArticle, + }); + } catch (error) { + if (error.code === "P2025") { + next(new NotFoundException(FAILED_DELETE_ARTICLE)); + } else { + next(error); + } + return; + } +}; + +export const patchArticle = async (req, res, next) => { + try { + const { articleId } = req.params; + const { title, content, images } = req.body; + + const updateArticle = await prisma.article.update({ + where: { id: parseInt(articleId) }, + data: { + title, + content, + images, + }, + }); + + if (!updateArticle) { + throw new NotFoundException(FAILED_UPDATE_ARTICLE); + } + + res.status(HttpStatus.OK).json({ + success: true, + message: "success update article", + data: updateArticle, + }); + } catch (error) { + next(error); + return; + } +}; + +export const patchArticleForView = async (req, res, next) => { + try { + const { articleId } = req.params; + + const updateArticle = await prisma.article.update({ + where: { id: parseInt(articleId) }, + data: { + view: { + increment: 1, + }, + }, + }); + + if (!updateArticle) { + throw new NotFoundException(FAILED_UPDATE_ARTICLE_VIEW); + } + + res.status(HttpStatus.OK).json({ + success: true, + message: "success update article", + data: updateArticle, + }); + } catch (error) { + next(error); + return; + } +}; diff --git a/src/routes/v1/articles.js b/src/routes/v1/articles.js index 9edb56e..6deb67a 100644 --- a/src/routes/v1/articles.js +++ b/src/routes/v1/articles.js @@ -8,207 +8,25 @@ import { FAILED_UPDATE_ARTICLE_VIEW, NOT_FOUND_ARTICLE, } from "../../common/constants/errorMessage.js"; +import { + createArticle, + deleteArticle, + getArticleById, + getArticles, + patchArticle, + patchArticleForView, +} from "../../controllers/v1/article.controller.js"; export const articleRouter = express.Router(); -articleRouter.get("/", async (req, res, next) => { - try { - const { - page: pageStr = 1, - limit: limitStr = 10, - keyword = "", - orderBy = "recent", - } = req.query; - - const page = parseInt(pageStr); - const limit = parseInt(limitStr); - const total = await prisma.article.count(); - const totalPage = Math.ceil(total / limit); - - const SORT_MAP = { - recent: { createdAt: "desc" }, - oldest: { createdAt: "asc" }, - }; - - const sortOptions = SORT_MAP[orderBy] ?? {}; - - const article = await prisma.article.findMany({ - where: { - OR: [ - { title: { contains: keyword, mode: "insensitive" } }, - { content: { contains: keyword, mode: "insensitive" } }, - ], - }, - include: { - author: { - include: { - userProfile: true, - }, - }, - }, - orderBy: sortOptions, - skip: limit * (page - 1), - take: limit, - }); - - res.status(HttpStatus.OK).json({ - success: true, - message: "success get articls", - data: article, - pagination: { - page, - limit, - total, - totalPage, - }, - }); - } catch (error) { - next(error); - return; - } -}); - -articleRouter.get("/:articleId", async (req, res, next) => { - try { - const { articleId } = req.params; - const article = await prisma.article.findUnique({ - where: { id: parseInt(articleId) }, - include: { - Comment: { - include: { - author: { - include: { - userProfile: true, - }, - }, - }, - }, - author: { - include: { - userProfile: true, - }, - }, - }, - }); - - if (!article) { - throw new NotFoundException(NOT_FOUND_ARTICLE); - } - - res.status(HttpStatus.OK).json({ - success: true, - message: "success get article", - data: article, - }); - } catch (error) { - next(error); - return; - } -}); - -articleRouter.post("/", async (req, res, next) => { - try { - const { title, content, images } = req.body; - - // TODO: userId - const newArticle = await prisma.article.create({ - data: { - title, - content, - images, - }, - }); - - res.status(HttpStatus.CREATED).json({ - success: true, - message: "success create article", - data: newArticle, - }); - } catch (error) { - next(error); - return; - } -}); - -articleRouter.patch("/:articleId", async (req, res, next) => { - try { - const { articleId } = req.params; - const { title, content, images } = req.body; - - const updateArticle = await prisma.article.update({ - where: { id: parseInt(articleId) }, - data: { - title, - content, - images, - }, - }); - - if (!updateArticle) { - throw new NotFoundException(FAILED_UPDATE_ARTICLE); - } - - res.status(HttpStatus.OK).json({ - success: true, - message: "success update article", - data: updateArticle, - }); - } catch (error) { - next(error); - return; - } -}); - -articleRouter.patch("/:articleId/views", async (req, res, next) => { - try { - const { articleId } = req.params; - - const updateArticle = await prisma.article.update({ - where: { id: parseInt(articleId) }, - data: { - view: { - increment: 1, - }, - }, - }); +articleRouter.get("/", getArticles); - if (!updateArticle) { - throw new NotFoundException(FAILED_UPDATE_ARTICLE_VIEW); - } +articleRouter.get("/:articleId", getArticleById); - res.status(HttpStatus.OK).json({ - success: true, - message: "success update article", - data: updateArticle, - }); - } catch (error) { - next(error); - return; - } -}); +articleRouter.post("/", createArticle); -articleRouter.delete("/:articleId", async (req, res, next) => { - try { - const { articleId } = req.params; - const deleteArticle = await prisma.article.delete({ - where: { id: parseInt(articleId) }, - }); +articleRouter.patch("/:articleId", patchArticle); - if (!deleteArticle) { - throw new NotFoundException(NOT_FOUND_ARTICLE); - } +articleRouter.patch("/:articleId/views", patchArticleForView); - res.status(HttpStatus.OK).json({ - success: true, - message: "success delete article", - data: deleteArticle, - }); - } catch (error) { - if (error.code === "P2025") { - next(new NotFoundException(FAILED_DELETE_ARTICLE)); - } else { - next(error); - } - return; - } -}); +articleRouter.delete("/:articleId", deleteArticle); From 9253177de33be69309afd3f23ba2eb79790072df Mon Sep 17 00:00:00 2001 From: rklpoi5678 Date: Sun, 5 Oct 2025 22:23:35 +0900 Subject: [PATCH 12/13] =?UTF-8?q?Rename:=20prittier=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prittier..config.js => prittier.config.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename prittier..config.js => prittier.config.js (100%) diff --git a/prittier..config.js b/prittier.config.js similarity index 100% rename from prittier..config.js rename to prittier.config.js From 2673963c2dea431dd360f101b0c033b9c6d9a618 Mon Sep 17 00:00:00 2001 From: rklpoi5678 Date: Sun, 5 Oct 2025 23:25:24 +0900 Subject: [PATCH 13/13] =?UTF-8?q?Style:=20(=ED=95=99=EC=8A=B5=EC=9A=A9)=20?= =?UTF-8?q?=EC=8B=9C=EB=94=A9=EC=9D=84=20=EC=9C=84=ED=95=9C=20jaker?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5b94264..d1b69c4 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "@prisma/client": "^6.16.2", "@swc/cli": "^0.7.8", "@swc/core": "^1.13.5", + "@faker-js/faker": "^10.0.0", "dotenv": "^17.2.2", "express": "^5.1.0", "swagger-autogen": "^2.23.7", @@ -51,7 +52,6 @@ }, "devDependencies": { "@eslint/js": "^9.36.0", - "@faker-js/faker": "^10.0.0", "@types/express": "^5.0.3", "@types/node": "^24.5.2", "eslint": "^9.36.0",